mirror of
https://github.com/S3NEO/android_kernel_samsung_msm8226.git
synced 2024-11-07 03:47:13 +00:00
misc: Remove Samsung Secure Data Protection sprinkles
* Will make upstream merges easier Change-Id: Ie0a5028235996f2bf233dc50489c1a9804b294de Signed-off-by: Kevin F. Haggerty <haggertk@lineageos.org>
This commit is contained in:
parent
ed185d55e9
commit
16d4fbdb9f
45 changed files with 1 additions and 5919 deletions
|
@ -28,17 +28,6 @@ config ECRYPT_FS_VIRTUAL_FAT_XATTR
|
|||
help
|
||||
Modification of encrypted filesystem for virtual FAT xattr
|
||||
|
||||
config SDP
|
||||
bool "Enables SDP"
|
||||
default n
|
||||
depends on ECRYPT_FS
|
||||
help
|
||||
Sensitive Data Protection
|
||||
|
||||
config SDP_KEY_DUMP
|
||||
bool "SDP KEY DUMP"
|
||||
default n
|
||||
|
||||
config FORCE_DISABLE_FIPS
|
||||
bool "Force disable FIPS config"
|
||||
default n
|
||||
|
|
|
@ -7,6 +7,5 @@ EXTRA_CFLAGS += -DECRYPT_FS_VIRTUAL_FAT_XATTR
|
|||
endif
|
||||
|
||||
obj-$(CONFIG_ECRYPT_FS) += ecryptfs.o
|
||||
obj-$(CONFIG_SDP) += ecryptfs_dek.o mm.o ecryptfs_sdp_chamber.o
|
||||
|
||||
ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o read_write.o crypto.o keystore.o messaging.o miscdev.o kthread.o debug.o
|
||||
|
|
|
@ -42,10 +42,6 @@
|
|||
#define SEED_LEN 32
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SDP
|
||||
#include "ecryptfs_dek.h"
|
||||
#endif
|
||||
|
||||
static int
|
||||
ecryptfs_decrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat,
|
||||
struct page *dst_page, int dst_offset,
|
||||
|
@ -515,12 +511,10 @@ static int encrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat,
|
|||
BUG_ON(!crypt_stat || !crypt_stat->tfm
|
||||
|| !(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED));
|
||||
if (unlikely(ecryptfs_verbosity > 0)) {
|
||||
#ifndef CONFIG_SDP
|
||||
ecryptfs_printk(KERN_DEBUG, "Key size [%zd]; key:\n",
|
||||
crypt_stat->key_size);
|
||||
ecryptfs_dump_hex(crypt_stat->key,
|
||||
crypt_stat->key_size);
|
||||
#endif
|
||||
}
|
||||
/* Consider doing this once, when the file is opened */
|
||||
mutex_lock(&crypt_stat->cs_tfm_mutex);
|
||||
|
@ -632,31 +626,6 @@ int ecryptfs_encrypt_page(struct page *page)
|
|||
crypt_stat =
|
||||
&(ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat);
|
||||
BUG_ON(!(crypt_stat->flags & ECRYPTFS_ENCRYPTED));
|
||||
#ifdef CONFIG_SDP
|
||||
if (!(crypt_stat->flags & ECRYPTFS_KEY_SET) ||
|
||||
!(crypt_stat->flags & ECRYPTFS_KEY_VALID)) {
|
||||
if((crypt_stat->flags & ECRYPTFS_DEK_SDP_ENABLED) &&
|
||||
(crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE)) {
|
||||
rc = ecryptfs_get_sdp_dek(crypt_stat);
|
||||
if (rc) {
|
||||
ecryptfs_printk(KERN_ERR, "%s Get SDP key failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
rc = ecryptfs_compute_root_iv(crypt_stat);
|
||||
if (rc) {
|
||||
ecryptfs_printk(KERN_ERR, "Error computing "
|
||||
"the root IV\n");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if ECRYPTFS_DEK_DEBUG
|
||||
ecryptfs_printk(KERN_ERR, "\tKEY [%zd]:\n", crypt_stat->key_size);
|
||||
ecryptfs_dump_hex(crypt_stat->key, crypt_stat->key_size);
|
||||
ecryptfs_printk(KERN_ERR, "\tIV [%zd]:\n", ECRYPTFS_MAX_IV_BYTES);
|
||||
ecryptfs_dump_hex(crypt_stat->root_iv, ECRYPTFS_MAX_IV_BYTES);
|
||||
#endif
|
||||
#endif
|
||||
enc_extent_page = alloc_page(GFP_USER);
|
||||
if (!enc_extent_page) {
|
||||
rc = -ENOMEM;
|
||||
|
@ -765,31 +734,6 @@ int ecryptfs_decrypt_page(struct page *page)
|
|||
crypt_stat =
|
||||
&(ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat);
|
||||
BUG_ON(!(crypt_stat->flags & ECRYPTFS_ENCRYPTED));
|
||||
#ifdef CONFIG_SDP
|
||||
if (!(crypt_stat->flags & ECRYPTFS_KEY_SET) ||
|
||||
!(crypt_stat->flags & ECRYPTFS_KEY_VALID)) {
|
||||
if((crypt_stat->flags & ECRYPTFS_DEK_SDP_ENABLED) &&
|
||||
(crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE)) {
|
||||
rc = ecryptfs_get_sdp_dek(crypt_stat);
|
||||
if (rc) {
|
||||
ecryptfs_printk(KERN_ERR, "%s Get SDP key failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
rc = ecryptfs_compute_root_iv(crypt_stat);
|
||||
if (rc) {
|
||||
ecryptfs_printk(KERN_ERR, "Error computing "
|
||||
"the root IV\n");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if ECRYPTFS_DEK_DEBUG
|
||||
ecryptfs_printk(KERN_ERR, "\tKEY [%zd]:\n", crypt_stat->key_size);
|
||||
ecryptfs_dump_hex(crypt_stat->key, crypt_stat->key_size);
|
||||
ecryptfs_printk(KERN_ERR, "\tIV [%zd]:\n", ECRYPTFS_MAX_IV_BYTES);
|
||||
ecryptfs_dump_hex(crypt_stat->root_iv, ECRYPTFS_MAX_IV_BYTES);
|
||||
#endif
|
||||
#endif
|
||||
enc_extent_page = alloc_page(GFP_USER);
|
||||
if (!enc_extent_page) {
|
||||
rc = -ENOMEM;
|
||||
|
@ -1111,11 +1055,6 @@ static void ecryptfs_copy_mount_wide_flags_to_inode_flags(
|
|||
& ECRYPTFS_GLOBAL_ENCFN_USE_FEK)
|
||||
crypt_stat->flags |= ECRYPTFS_ENCFN_USE_FEK;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SDP
|
||||
if (mount_crypt_stat->flags & ECRYPTFS_MOUNT_SDP_ENABLED)
|
||||
crypt_stat->flags |= ECRYPTFS_DEK_SDP_ENABLED;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int ecryptfs_copy_mount_wide_sigs_to_inode_sigs(
|
||||
|
@ -1165,9 +1104,6 @@ static void ecryptfs_set_default_crypt_stat_vals(
|
|||
crypt_stat->flags &= ~(ECRYPTFS_KEY_VALID);
|
||||
crypt_stat->file_version = ECRYPTFS_FILE_VERSION;
|
||||
crypt_stat->mount_crypt_stat = mount_crypt_stat;
|
||||
#ifdef CONFIG_SDP
|
||||
crypt_stat->engine_id = -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1260,14 +1196,7 @@ static struct ecryptfs_flag_map_elem ecryptfs_flag_map[] = {
|
|||
{0x00000001, ECRYPTFS_ENABLE_HMAC},
|
||||
{0x00000002, ECRYPTFS_ENCRYPTED},
|
||||
{0x00000004, ECRYPTFS_METADATA_IN_XATTR},
|
||||
#ifdef CONFIG_SDP
|
||||
{0x00000008, ECRYPTFS_ENCRYPT_FILENAMES},
|
||||
{0x00100000, ECRYPTFS_DEK_SDP_ENABLED},
|
||||
{0x00200000, ECRYPTFS_DEK_IS_SENSITIVE},
|
||||
{0x00400000, ECRYPTFS_DEK_MULTI_ENGINE},
|
||||
#else
|
||||
{0x00000008, ECRYPTFS_ENCRYPT_FILENAMES},
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1587,18 +1516,6 @@ int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry,
|
|||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
#ifdef CONFIG_SDP
|
||||
#if ECRYPTFS_DEK_DEBUG
|
||||
ecryptfs_printk(KERN_INFO, "name is [%s], flag is %d\n",
|
||||
ecryptfs_dentry->d_name.name, crypt_stat->flags);
|
||||
if (crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE) {
|
||||
ecryptfs_printk(KERN_INFO, "is sensitive\n");
|
||||
}
|
||||
else{
|
||||
ecryptfs_printk(KERN_INFO, "is protected\n");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
virt_len = crypt_stat->metadata_size;
|
||||
order = get_order(virt_len);
|
||||
/* Released in this function */
|
||||
|
@ -1842,14 +1759,6 @@ int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry)
|
|||
rc = ecryptfs_read_headers_virt(page_virt, crypt_stat,
|
||||
ecryptfs_dentry,
|
||||
ECRYPTFS_VALIDATE_HEADER_SIZE);
|
||||
#ifdef CONFIG_SDP
|
||||
if ((rc) && crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE)
|
||||
/*
|
||||
* metadata is not in the file header, SDP sensitive file.
|
||||
* Don't check xattr region. we don't put info there.
|
||||
*/
|
||||
goto out;
|
||||
#endif
|
||||
if (rc) {
|
||||
/* metadata is not in the file header, so try xattrs */
|
||||
memset(page_virt, 0, PAGE_CACHE_SIZE);
|
||||
|
@ -1884,24 +1793,6 @@ int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SDP
|
||||
#if ECRYPTFS_DEK_DEBUG
|
||||
ecryptfs_printk(KERN_INFO, "name is [%s], flag is %d\n",
|
||||
ecryptfs_dentry->d_name.name, crypt_stat->flags);
|
||||
if (crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE) {
|
||||
ecryptfs_printk(KERN_INFO, "dek_file_type is sensitive, enc type=%d\n",
|
||||
crypt_stat->sdp_dek.type);
|
||||
if (ecryptfs_is_persona_locked(crypt_stat->engine_id)) {
|
||||
ecryptfs_printk(KERN_INFO, "persona is locked, rc=%d\n", rc);
|
||||
} else {
|
||||
ecryptfs_printk(KERN_INFO, "persona is unlocked, rc=%d\n", rc);
|
||||
}
|
||||
} else {
|
||||
ecryptfs_printk(KERN_INFO, "dek_file_type is protected\n");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
out:
|
||||
if (page_virt) {
|
||||
memset(page_virt, 0, PAGE_CACHE_SIZE);
|
||||
|
|
|
@ -95,7 +95,6 @@ void ecryptfs_dump_auth_tok(struct ecryptfs_auth_tok *auth_tok)
|
|||
*
|
||||
* Dump hexadecimal representation of char array
|
||||
*/
|
||||
#ifndef CONFIG_SDP
|
||||
void ecryptfs_dump_hex(char *data, int bytes)
|
||||
{
|
||||
int i = 0;
|
||||
|
@ -119,8 +118,3 @@ void ecryptfs_dump_hex(char *data, int bytes)
|
|||
if (add_newline)
|
||||
printk("\n");
|
||||
}
|
||||
#else
|
||||
void ecryptfs_dump_hex(char *data, int bytes)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,781 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Sensitive Data Protection
|
||||
*
|
||||
* 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 <linux/pagemap.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include <sdp/fs_handler.h>
|
||||
#include "ecryptfs_dek.h"
|
||||
#include "ecryptfs_sdp_chamber.h"
|
||||
#include "mm.h"
|
||||
|
||||
extern int dek_encrypt_dek_efs(int engine_id, dek_t *plainDek, dek_t *encDek);
|
||||
extern int dek_decrypt_dek_efs(int engine_id, dek_t *encDek, dek_t *plainDek);
|
||||
extern int dek_is_locked(int engine_id);
|
||||
|
||||
static int ecryptfs_update_crypt_flag(struct dentry *dentry, enum sdp_op operation);
|
||||
|
||||
static const char* get_op_name(enum sdp_op operation) {
|
||||
switch (operation)
|
||||
{
|
||||
case TO_SENSITIVE: return "TO_SENSITIVE";
|
||||
case TO_PROTECTED: return "TO_PROTECTED";
|
||||
default: return "OP_UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
static int ecryptfs_set_key(struct ecryptfs_crypt_stat *crypt_stat) {
|
||||
int rc = 0;
|
||||
|
||||
mutex_lock(&crypt_stat->cs_tfm_mutex);
|
||||
if (!(crypt_stat->flags & ECRYPTFS_KEY_SET)) {
|
||||
rc = crypto_blkcipher_setkey(crypt_stat->tfm, crypt_stat->key,
|
||||
crypt_stat->key_size);
|
||||
if (rc) {
|
||||
ecryptfs_printk(KERN_ERR,
|
||||
"Error setting key; rc = [%d]\n",
|
||||
rc);
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
crypt_stat->flags |= ECRYPTFS_KEY_SET;
|
||||
crypt_stat->flags |= ECRYPTFS_KEY_VALID;
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&crypt_stat->cs_tfm_mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int ecryptfs_is_sdp_locked(int engine_id)
|
||||
{
|
||||
if(engine_id < 0) {
|
||||
DEK_LOGE("invalid engine_id[%d]\n", engine_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return dek_is_locked(engine_id);
|
||||
}
|
||||
|
||||
extern int32_t sdp_mm_set_process_sensitive(unsigned int proc_id);
|
||||
|
||||
#define PSEUDO_KEY_LEN 32
|
||||
const char pseudo_key[PSEUDO_KEY_LEN] = {
|
||||
// PSEUDOSDP
|
||||
0x50, 0x53, 0x55, 0x45, 0x44, 0x4f, 0x53, 0x44,
|
||||
0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
void ecryptfs_clean_sdp_dek(struct ecryptfs_crypt_stat *crypt_stat)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
printk("%s()\n", __func__);
|
||||
|
||||
if(crypt_stat->tfm) {
|
||||
mutex_lock(&crypt_stat->cs_tfm_mutex);
|
||||
rc = crypto_blkcipher_setkey(crypt_stat->tfm, pseudo_key,
|
||||
PSEUDO_KEY_LEN);
|
||||
if (rc) {
|
||||
ecryptfs_printk(KERN_ERR,
|
||||
"Error cleaning tfm rc = [%d]\n",
|
||||
rc);
|
||||
}
|
||||
mutex_unlock(&crypt_stat->cs_tfm_mutex);
|
||||
}
|
||||
|
||||
memset(crypt_stat->key, 0, ECRYPTFS_MAX_KEY_BYTES);
|
||||
crypt_stat->flags &= ~(ECRYPTFS_KEY_SET);
|
||||
crypt_stat->flags &= ~(ECRYPTFS_KEY_VALID);
|
||||
}
|
||||
|
||||
int ecryptfs_get_sdp_dek(struct ecryptfs_crypt_stat *crypt_stat)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if(crypt_stat->flags & ECRYPTFS_KEY_SET) {
|
||||
DEK_LOGE("get_sdp_dek: key is already set (success)\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(crypt_stat->flags & ECRYPTFS_DEK_SDP_ENABLED) {
|
||||
if(crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE) {
|
||||
dek_t DEK;
|
||||
|
||||
if(crypt_stat->engine_id < 0) {
|
||||
DEK_LOGE("get_sdp_dek: invalid engine-id"
|
||||
"(ECRYPTFS_DEK_IS_SENSITIVE:ON, engine_id:%d)\n", crypt_stat->engine_id);
|
||||
goto out;
|
||||
}
|
||||
memset(crypt_stat->key, 0, ECRYPTFS_MAX_KEY_BYTES);
|
||||
|
||||
if (crypt_stat->sdp_dek.type != DEK_TYPE_PLAIN) {
|
||||
rc = dek_decrypt_dek_efs(crypt_stat->engine_id, &crypt_stat->sdp_dek, &DEK);
|
||||
} else {
|
||||
DEK_LOGE("DEK already plaintext, skip decryption");
|
||||
rc = 0;
|
||||
goto out;
|
||||
}
|
||||
if (rc < 0) {
|
||||
DEK_LOGE("Error decypting dek; rc = [%d]\n", rc);
|
||||
memset(&DEK, 0, sizeof(dek_t));
|
||||
goto out;
|
||||
}
|
||||
memcpy(crypt_stat->key, DEK.buf, DEK.len);
|
||||
crypt_stat->key_size = DEK.len;
|
||||
memset(&DEK, 0, sizeof(dek_t));
|
||||
} else {
|
||||
#if ECRYPTFS_DEK_DEBUG
|
||||
DEK_LOGD("file is not sensitive\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
out:
|
||||
/*
|
||||
* Succeeded
|
||||
*/
|
||||
if(!rc) {
|
||||
sdp_mm_set_process_sensitive(current->pid);
|
||||
rc = ecryptfs_set_key(crypt_stat);
|
||||
} else {
|
||||
/*
|
||||
* Error
|
||||
*/
|
||||
ecryptfs_clean_sdp_dek(crypt_stat);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int write_dek_packet(char *dest,
|
||||
struct ecryptfs_crypt_stat *crypt_stat,
|
||||
size_t *written) {
|
||||
*written = 0;
|
||||
dest[(*written)++] = ECRYPTFS_DEK_PACKET_TYPE;
|
||||
|
||||
memset(dest + *written, 0, PKG_NAME_SIZE);
|
||||
memcpy(dest + *written, current->comm, PKG_NAME_SIZE);
|
||||
(*written) += PKG_NAME_SIZE;
|
||||
|
||||
put_unaligned_be32(current_euid(), dest + *written);
|
||||
(*written) += 4;
|
||||
|
||||
memset(dest + *written, 0, DEK_MAXLEN);
|
||||
|
||||
if (crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE) {
|
||||
if(crypt_stat->flags & ECRYPTFS_DEK_MULTI_ENGINE) {
|
||||
put_unaligned_be32(crypt_stat->engine_id, dest + *written);
|
||||
(*written) += 4;
|
||||
}
|
||||
|
||||
put_unaligned_be32(crypt_stat->sdp_dek.type, dest + *written);
|
||||
(*written) += 4;
|
||||
put_unaligned_be32(crypt_stat->sdp_dek.len, dest + *written);
|
||||
(*written) += 4;
|
||||
memcpy(dest + *written, crypt_stat->sdp_dek.buf, crypt_stat->sdp_dek.len);
|
||||
(*written) += crypt_stat->sdp_dek.len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_dek_packet(char *data,
|
||||
struct ecryptfs_crypt_stat *crypt_stat,
|
||||
size_t *packet_size) {
|
||||
int rc = 0;
|
||||
char temp_comm[PKG_NAME_SIZE]; //test
|
||||
int temp_euid;
|
||||
int sdp_dek_type;
|
||||
int sdp_dek_len;
|
||||
|
||||
if (crypt_stat->file_version == 0)
|
||||
return -EPERM;
|
||||
|
||||
(*packet_size) = 0;
|
||||
|
||||
if (data[(*packet_size)++] != ECRYPTFS_DEK_PACKET_TYPE) {
|
||||
DEK_LOGE("First byte != 0x%.2x; invalid packet\n",
|
||||
ECRYPTFS_DEK_PACKET_TYPE);
|
||||
rc = -EINVAL;
|
||||
}
|
||||
|
||||
memcpy(temp_comm, &data[*packet_size], PKG_NAME_SIZE);
|
||||
(*packet_size) += PKG_NAME_SIZE;
|
||||
|
||||
temp_euid = get_unaligned_be32(data + *packet_size);
|
||||
(*packet_size) += 4;
|
||||
|
||||
if (crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE) {
|
||||
if(crypt_stat->flags & ECRYPTFS_DEK_MULTI_ENGINE) {
|
||||
crypt_stat->engine_id = get_unaligned_be32(data + *packet_size);
|
||||
(*packet_size) += 4;
|
||||
} else {
|
||||
/**
|
||||
* If eCryptfs header doesn't have engine-id,
|
||||
* we assign it from mount_crypt_stat->userid
|
||||
* (Fils created in old version)
|
||||
*/
|
||||
crypt_stat->engine_id = crypt_stat->mount_crypt_stat->userid;
|
||||
}
|
||||
|
||||
sdp_dek_type = get_unaligned_be32(data + *packet_size);
|
||||
if(sdp_dek_type < 0 || sdp_dek_type > 6)
|
||||
return -EINVAL;
|
||||
crypt_stat->sdp_dek.type = sdp_dek_type;
|
||||
(*packet_size) += 4;
|
||||
|
||||
sdp_dek_len = get_unaligned_be32(data + *packet_size);
|
||||
if(sdp_dek_len <= 0 || sdp_dek_len > DEK_MAXLEN)
|
||||
return -EFAULT;
|
||||
crypt_stat->sdp_dek.len = sdp_dek_len;
|
||||
(*packet_size) += 4;
|
||||
|
||||
|
||||
memcpy(crypt_stat->sdp_dek.buf, &data[*packet_size], crypt_stat->sdp_dek.len);
|
||||
(*packet_size) += crypt_stat->sdp_dek.len;
|
||||
}
|
||||
|
||||
#if ECRYPTFS_DEK_DEBUG
|
||||
DEK_LOGD("%s() : comm : %s [euid:%d]\n",
|
||||
__func__, temp_comm, temp_euid);
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int ecryptfs_dek_copy_mount_wide_sigs_to_inode_sigs(
|
||||
struct ecryptfs_crypt_stat *crypt_stat,
|
||||
struct ecryptfs_mount_crypt_stat *mount_crypt_stat)
|
||||
{
|
||||
struct ecryptfs_global_auth_tok *global_auth_tok;
|
||||
int rc = 0;
|
||||
|
||||
mutex_lock(&crypt_stat->keysig_list_mutex);
|
||||
mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex);
|
||||
|
||||
list_for_each_entry(global_auth_tok,
|
||||
&mount_crypt_stat->global_auth_tok_list,
|
||||
mount_crypt_stat_list) {
|
||||
if (global_auth_tok->flags & ECRYPTFS_AUTH_TOK_FNEK)
|
||||
continue;
|
||||
rc = ecryptfs_add_keysig(crypt_stat, global_auth_tok->sig);
|
||||
if (rc) {
|
||||
printk(KERN_ERR "Error adding keysig; rc = [%d]\n", rc);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex);
|
||||
mutex_unlock(&crypt_stat->keysig_list_mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_MMC_DW_FMP_ECRYPT_FS) || defined(CONFIG_UFS_FMP_ECRYPT_FS)
|
||||
static void ecryptfs_propagate_flag(struct file *file, int userid, enum sdp_op operation) {
|
||||
struct file *f = file;
|
||||
do {
|
||||
if(!f)
|
||||
return ;
|
||||
|
||||
DEK_LOGD("%s file: %p [%s]\n",__func__, f, f->f_inode->i_sb->s_type->name);
|
||||
if (operation == TO_SENSITIVE) {
|
||||
mapping_set_sensitive(f->f_mapping);
|
||||
} else {
|
||||
mapping_clear_sensitive(f->f_mapping);
|
||||
}
|
||||
f->f_mapping->userid = userid;
|
||||
} while (f->f_op->get_lower_file && (f = f->f_op->get_lower_file(f)));
|
||||
}
|
||||
#endif
|
||||
|
||||
void ecryptfs_set_mapping_sensitive(struct inode *ecryptfs_inode, int userid, enum sdp_op operation) {
|
||||
#if defined(CONFIG_MMC_DW_FMP_ECRYPT_FS) || defined(CONFIG_UFS_FMP_ECRYPT_FS)
|
||||
struct ecryptfs_mount_crypt_stat *mount_crypt_stat = NULL;
|
||||
struct ecryptfs_inode_info *inode_info;
|
||||
|
||||
inode_info = ecryptfs_inode_to_private(ecryptfs_inode);
|
||||
DEK_LOGD("%s inode: %p lower_file_count: %d\n",__func__, ecryptfs_inode,atomic_read(&inode_info->lower_file_count));
|
||||
mount_crypt_stat = &ecryptfs_superblock_to_private(ecryptfs_inode->i_sb)->mount_crypt_stat;
|
||||
|
||||
if (operation == TO_SENSITIVE) {
|
||||
mapping_set_sensitive(ecryptfs_inode->i_mapping);
|
||||
} else {
|
||||
mapping_clear_sensitive(ecryptfs_inode->i_mapping);
|
||||
}
|
||||
ecryptfs_inode->i_mapping->userid = userid;
|
||||
/*
|
||||
* If FMP is in use, need to set flag to lower filesystems too recursively
|
||||
*/
|
||||
if (mount_crypt_stat->flags & ECRYPTFS_USE_FMP) {
|
||||
if(inode_info->lower_file) {
|
||||
ecryptfs_propagate_flag(inode_info->lower_file, userid, operation);
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (operation == TO_SENSITIVE) {
|
||||
mapping_set_sensitive(ecryptfs_inode->i_mapping);
|
||||
} else {
|
||||
mapping_clear_sensitive(ecryptfs_inode->i_mapping);
|
||||
}
|
||||
ecryptfs_inode->i_mapping->userid = userid;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* set sensitive flag, update metadata
|
||||
* Set cached inode pages to sensitive
|
||||
*/
|
||||
static int ecryptfs_update_crypt_flag(struct dentry *dentry, enum sdp_op operation)
|
||||
{
|
||||
int rc = 0;
|
||||
struct inode *inode;
|
||||
struct inode *lower_inode;
|
||||
struct ecryptfs_crypt_stat *crypt_stat;
|
||||
struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
|
||||
u32 tmp_flags;
|
||||
|
||||
DEK_LOGE("%s(operation:%s) entered\n", __func__, get_op_name(operation));
|
||||
|
||||
crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat;
|
||||
mount_crypt_stat = &ecryptfs_superblock_to_private(dentry->d_sb)->mount_crypt_stat;
|
||||
if (!(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED))
|
||||
ecryptfs_init_crypt_stat(crypt_stat);
|
||||
inode = dentry->d_inode;
|
||||
lower_inode = ecryptfs_inode_to_lower(inode);
|
||||
|
||||
/*
|
||||
* To update metadata we need to make sure keysig_list contains fekek.
|
||||
* Because our EDEK is stored along with key for protected file.
|
||||
*/
|
||||
if(list_empty(&crypt_stat->keysig_list))
|
||||
ecryptfs_dek_copy_mount_wide_sigs_to_inode_sigs(crypt_stat, mount_crypt_stat);
|
||||
|
||||
mutex_lock(&crypt_stat->cs_mutex);
|
||||
rc = ecryptfs_get_lower_file(dentry, inode);
|
||||
if (rc) {
|
||||
mutex_unlock(&crypt_stat->cs_mutex);
|
||||
DEK_LOGE("ecryptfs_get_lower_file rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
tmp_flags = crypt_stat->flags;
|
||||
if (operation == TO_SENSITIVE) {
|
||||
crypt_stat->flags |= ECRYPTFS_DEK_IS_SENSITIVE;
|
||||
crypt_stat->flags |= ECRYPTFS_DEK_MULTI_ENGINE;
|
||||
/*
|
||||
* Set sensitive to inode mapping
|
||||
*/
|
||||
ecryptfs_set_mapping_sensitive(inode, mount_crypt_stat->userid, TO_SENSITIVE);
|
||||
} else {
|
||||
crypt_stat->flags &= ~ECRYPTFS_DEK_IS_SENSITIVE;
|
||||
crypt_stat->flags &= ~ECRYPTFS_DEK_MULTI_ENGINE;
|
||||
|
||||
/*
|
||||
* Set protected to inode mapping
|
||||
*/
|
||||
ecryptfs_set_mapping_sensitive(inode, mount_crypt_stat->userid, TO_PROTECTED);
|
||||
}
|
||||
|
||||
rc = ecryptfs_write_metadata(dentry, inode);
|
||||
if (rc) {
|
||||
crypt_stat->flags = tmp_flags;
|
||||
DEK_LOGE("ecryptfs_write_metadata rc=%d\n", rc);
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = ecryptfs_write_inode_size_to_metadata(inode);
|
||||
if (rc) {
|
||||
DEK_LOGE("Problem with "
|
||||
"ecryptfs_write_inode_size_to_metadata; "
|
||||
"rc = [%d]\n", rc);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&crypt_stat->cs_mutex);
|
||||
ecryptfs_put_lower_file(inode);
|
||||
fsstack_copy_attr_all(inode, lower_inode);
|
||||
return rc;
|
||||
}
|
||||
|
||||
void ecryptfs_fs_request_callback(int opcode, int ret, unsigned long ino) {
|
||||
DEK_LOGD("%s opcode<%d> ret<%d> ino<%ld>\n", __func__, opcode, ret, ino);
|
||||
}
|
||||
|
||||
int ecryptfs_sdp_set_sensitive(int engine_id, struct dentry *dentry) {
|
||||
int rc = 0;
|
||||
struct inode *inode = dentry->d_inode;
|
||||
struct ecryptfs_crypt_stat *crypt_stat =
|
||||
&ecryptfs_inode_to_private(inode)->crypt_stat;
|
||||
dek_t DEK;
|
||||
int id_bak = crypt_stat->engine_id;
|
||||
|
||||
DEK_LOGD("%s(%s)\n", __func__, dentry->d_name.name);
|
||||
|
||||
if(S_ISDIR(inode->i_mode)) {
|
||||
crypt_stat->engine_id = engine_id;
|
||||
crypt_stat->flags |= ECRYPTFS_DEK_IS_SENSITIVE;
|
||||
|
||||
rc = 0;
|
||||
} else if(S_ISREG(inode->i_mode)) {
|
||||
crypt_stat->engine_id = engine_id;
|
||||
|
||||
if (crypt_stat->key_size > ECRYPTFS_MAX_KEY_BYTES ||
|
||||
crypt_stat->key_size > DEK_MAXLEN ||
|
||||
crypt_stat->key_size > UINT_MAX){
|
||||
DEK_LOGE("%s Too large key_size\n", __func__);
|
||||
rc = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
memcpy(DEK.buf, crypt_stat->key, crypt_stat->key_size);
|
||||
DEK.len = (unsigned int)crypt_stat->key_size;
|
||||
DEK.type = DEK_TYPE_PLAIN;
|
||||
|
||||
rc = dek_encrypt_dek_efs(crypt_stat->engine_id, &DEK, &crypt_stat->sdp_dek);
|
||||
if (rc < 0) {
|
||||
DEK_LOGE("Error encrypting dek; rc = [%d]\n", rc);
|
||||
memset(&crypt_stat->sdp_dek, 0, sizeof(dek_t));
|
||||
goto out;
|
||||
}
|
||||
#if 0
|
||||
/*
|
||||
* We don't have to clear FEK after set-sensitive.
|
||||
* FEK will be closed when the file is closed
|
||||
*/
|
||||
memset(crypt_stat->key, 0, crypt_stat->key_size);
|
||||
crypt_stat->flags &= ~(ECRYPTFS_KEY_SET);
|
||||
#else
|
||||
/*
|
||||
* set-key after set sensitive file.
|
||||
* Well when the file is just created and we do set_sensitive, the key is not set in the
|
||||
* tfm. later SDP code, set-key is done while encryption, trying to decrypt EFEK.
|
||||
*
|
||||
* Here is the case in locked state user process want to create/write a file.
|
||||
* the process open the file, automatically becomes sensitive by vault logic,
|
||||
* and do the encryption, then boom. failed to decrypt EFEK even if FEK is
|
||||
* available
|
||||
*/
|
||||
rc = ecryptfs_set_key(crypt_stat);
|
||||
if(rc) goto out;
|
||||
#endif
|
||||
|
||||
ecryptfs_update_crypt_flag(dentry, TO_SENSITIVE);
|
||||
}
|
||||
|
||||
out:
|
||||
if(rc) crypt_stat->engine_id = id_bak;
|
||||
memset(&DEK, 0, sizeof(dek_t));
|
||||
return rc;
|
||||
}
|
||||
|
||||
int ecryptfs_sdp_set_protected(struct dentry *dentry) {
|
||||
int rc = 0;
|
||||
struct inode *inode = dentry->d_inode;
|
||||
struct ecryptfs_crypt_stat *crypt_stat =
|
||||
&ecryptfs_inode_to_private(inode)->crypt_stat;
|
||||
|
||||
DEK_LOGD("%s(%s)\n", __func__, dentry->d_name.name);
|
||||
|
||||
if(IS_CHAMBER_DENTRY(dentry)) {
|
||||
DEK_LOGE("can't set-protected to chamber directory");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if(crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE) {
|
||||
if(crypt_stat->engine_id < 0) {
|
||||
DEK_LOGE("%s: invalid engine-id (ECRYPTFS_DEK_IS_SENSITIVE:ON, engine_id:%d)\n",
|
||||
__func__, crypt_stat->engine_id);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if(ecryptfs_is_sdp_locked(crypt_stat->engine_id)) {
|
||||
DEK_LOGE("%s: Failed. (engine_id:%d locked)\n",
|
||||
__func__, crypt_stat->engine_id);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if(S_ISDIR(inode->i_mode)) {
|
||||
crypt_stat->flags &= ~ECRYPTFS_DEK_IS_SENSITIVE;
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = ecryptfs_get_sdp_dek(crypt_stat);
|
||||
if (rc) {
|
||||
ecryptfs_printk(KERN_ERR, "%s Get SDP key failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
/*
|
||||
* TODO : double check if need to compute iv here
|
||||
*/
|
||||
rc = ecryptfs_compute_root_iv(crypt_stat);
|
||||
if (rc) {
|
||||
ecryptfs_printk(KERN_ERR, "Error computing "
|
||||
"the root IV\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = ecryptfs_set_key(crypt_stat);
|
||||
if(rc) goto out;
|
||||
|
||||
ecryptfs_update_crypt_flag(dentry, TO_PROTECTED);
|
||||
}
|
||||
} else {
|
||||
rc = 0; //already protected
|
||||
}
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int ecryptfs_sdp_convert_dek(struct dentry *dentry) {
|
||||
int rc = 0;
|
||||
struct inode *inode = dentry->d_inode;
|
||||
struct ecryptfs_crypt_stat *crypt_stat =
|
||||
&ecryptfs_inode_to_private(inode)->crypt_stat;
|
||||
dek_t DEK;
|
||||
|
||||
rc = dek_decrypt_dek_efs(crypt_stat->engine_id, &crypt_stat->sdp_dek, &DEK);
|
||||
if (rc < 0) {
|
||||
DEK_LOGE("Error converting dek [DEC]; rc = [%d]\n", rc);
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = dek_encrypt_dek_efs(crypt_stat->engine_id, &DEK, &crypt_stat->sdp_dek);
|
||||
if (rc < 0) {
|
||||
DEK_LOGE("Error converting dek [ENC]; rc = [%d]\n", rc);
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = ecryptfs_update_crypt_flag(dentry, TO_SENSITIVE);
|
||||
if (rc < 0) {
|
||||
DEK_LOGE("Error converting dek [FLAG]; rc = [%d]\n", rc);
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
memset(&DEK, 0, sizeof(dek_t));
|
||||
return rc;
|
||||
}
|
||||
|
||||
long ecryptfs_do_sdp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) {
|
||||
char filename[NAME_MAX+1] = {0};
|
||||
void __user *ubuf = (void __user *)arg;
|
||||
struct dentry *ecryptfs_dentry = file->f_path.dentry;
|
||||
struct inode *inode = ecryptfs_dentry->d_inode;
|
||||
struct ecryptfs_crypt_stat *crypt_stat =
|
||||
&ecryptfs_inode_to_private(inode)->crypt_stat;
|
||||
struct dentry *fp_dentry =
|
||||
ecryptfs_inode_to_private(inode)->lower_file->f_dentry;
|
||||
struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
|
||||
&ecryptfs_superblock_to_private(inode->i_sb)->mount_crypt_stat;
|
||||
int rc;
|
||||
|
||||
if (fp_dentry->d_name.len <= NAME_MAX)
|
||||
memcpy(filename, fp_dentry->d_name.name,
|
||||
fp_dentry->d_name.len + 1);
|
||||
|
||||
DEK_LOGD("%s(%s)\n", __func__, ecryptfs_dentry->d_name.name);
|
||||
|
||||
if (!(crypt_stat->flags & ECRYPTFS_DEK_SDP_ENABLED)) {
|
||||
DEK_LOGE("SDP not enabled, skip sdp ioctl\n");
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case ECRYPTFS_IOCTL_GET_SDP_INFO: {
|
||||
dek_arg_get_sdp_info req;
|
||||
|
||||
DEK_LOGD("ECRYPTFS_IOCTL_GET_SDP_INFO\n");
|
||||
|
||||
memset(&req, 0, sizeof(dek_arg_get_sdp_info));
|
||||
if(copy_from_user(&req, ubuf, sizeof(req))) {
|
||||
DEK_LOGE("can't copy from user\n");
|
||||
return -EFAULT;
|
||||
} else {
|
||||
mutex_lock(&crypt_stat->cs_mutex);
|
||||
|
||||
req.engine_id = crypt_stat->engine_id;
|
||||
|
||||
if (crypt_stat->flags & ECRYPTFS_DEK_SDP_ENABLED) {
|
||||
req.sdp_enabled = 1;
|
||||
} else {
|
||||
req.sdp_enabled = 0;
|
||||
}
|
||||
if (crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE) {
|
||||
req.is_sensitive = 1;
|
||||
} else {
|
||||
req.is_sensitive = 0;
|
||||
}
|
||||
if (crypt_stat->flags & ECRYPTFS_SDP_IS_CHAMBER_DIR) {
|
||||
req.is_chamber = 1;
|
||||
} else {
|
||||
req.is_chamber = 0;
|
||||
}
|
||||
req.type = crypt_stat->sdp_dek.type;
|
||||
mutex_unlock(&crypt_stat->cs_mutex);
|
||||
}
|
||||
if(copy_to_user(ubuf, &req, sizeof(req))) {
|
||||
DEK_LOGE("can't copy to user\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ECRYPTFS_IOCTL_SET_PROTECTED: {
|
||||
ecryptfs_printk(KERN_DEBUG, "ECRYPTFS_IOCTL_SET_PROTECTED\n");
|
||||
|
||||
if(!is_current_epmd()) {
|
||||
DEK_LOGE("only epmd can call this\n");
|
||||
DEK_LOGE("Permission denied\n");
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
if (!(crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE)) {
|
||||
DEK_LOGE("already protected file\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) {
|
||||
DEK_LOGE("Set protected directory\n");
|
||||
crypt_stat->flags &= ~ECRYPTFS_DEK_IS_SENSITIVE;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = ecryptfs_sdp_set_protected(ecryptfs_dentry);
|
||||
if (rc) {
|
||||
DEK_LOGE("Failed to set protected rc(%d)\n", rc);
|
||||
return rc;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ECRYPTFS_IOCTL_SET_SENSITIVE: {
|
||||
dek_arg_set_sensitive req;
|
||||
|
||||
ecryptfs_printk(KERN_DEBUG, "ECRYPTFS_IOCTL_SET_SENSITIVE\n");
|
||||
if (crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE) {
|
||||
DEK_LOGE("already sensitive file\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(&req, 0, sizeof(dek_arg_set_sensitive));
|
||||
if(copy_from_user(&req, ubuf, sizeof(req))) {
|
||||
DEK_LOGE("can't copy from user\n");
|
||||
memset(&req, 0, sizeof(dek_arg_set_sensitive));
|
||||
return -EFAULT;
|
||||
} else {
|
||||
rc = ecryptfs_sdp_set_sensitive(req.engine_id, ecryptfs_dentry);
|
||||
if (rc) {
|
||||
DEK_LOGE("failed to set sensitive rc(%d)\n", rc);
|
||||
memset(&req, 0, sizeof(dek_arg_set_sensitive));
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
memset(&req, 0, sizeof(dek_arg_set_sensitive));
|
||||
break;
|
||||
}
|
||||
|
||||
case ECRYPTFS_IOCTL_ADD_CHAMBER: {
|
||||
dek_arg_add_chamber req;
|
||||
int engineid;
|
||||
|
||||
if (!S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) {
|
||||
DEK_LOGE("Not a directory\n");
|
||||
return -ENOTDIR;
|
||||
}
|
||||
|
||||
if(!is_current_epmd()) {
|
||||
DEK_LOGE("only epmd can call this\n");
|
||||
DEK_LOGE("Permission denied\n");
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
if(copy_from_user(&req, ubuf, sizeof(req))) {
|
||||
DEK_LOGE("can't copy from user\n");
|
||||
memset(&req, 0, sizeof(req));
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if(!IS_UNDER_ROOT(ecryptfs_dentry)) {
|
||||
DEK_LOGE("Chamber has to be under root directory");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if(is_chamber_directory(mount_crypt_stat, ecryptfs_dentry->d_name.name, &engineid)) {
|
||||
DEK_LOGE("Already chamber directory [%s] engine:%d\n",
|
||||
ecryptfs_dentry->d_name.name, engineid);
|
||||
if(engineid != req.engine_id) {
|
||||
DEK_LOGE("Attemping to change engine-id[%d] -> [%d] : Failed\n",
|
||||
engineid, req.engine_id);
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
set_chamber_flag(engineid, inode);
|
||||
break;
|
||||
}
|
||||
|
||||
rc = add_chamber_directory(mount_crypt_stat, req.engine_id,
|
||||
ecryptfs_dentry->d_name.name);
|
||||
if(rc) {
|
||||
DEK_LOGE("add_chamber_directory failed. %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
set_chamber_flag(req.engine_id, inode);
|
||||
break;
|
||||
}
|
||||
|
||||
case ECRYPTFS_IOCTL_REMOVE_CHAMBER: {
|
||||
if (!S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) {
|
||||
DEK_LOGE("Not a directory\n");
|
||||
return -ENOTDIR;
|
||||
}
|
||||
|
||||
if(!is_current_epmd()) {
|
||||
//DEK_LOGE("only epmd can call this");
|
||||
DEK_LOGE("Permission denied");
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
if(!IS_UNDER_ROOT(ecryptfs_dentry)) {
|
||||
DEK_LOGE("Chamber has to be under root directory");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if(!is_chamber_directory(mount_crypt_stat, ecryptfs_dentry->d_name.name, NULL)) {
|
||||
DEK_LOGE("Not a chamber directory [%s]\n", ecryptfs_dentry->d_name.name);
|
||||
|
||||
clr_chamber_flag(inode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
del_chamber_directory(mount_crypt_stat, ecryptfs_dentry->d_name.name);
|
||||
clr_chamber_flag(inode);
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
return -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -1,84 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Sensitive Data Protection
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef ECRYPTFS_DEK_H
|
||||
#define ECRYPTFS_DEK_H
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <sdp/dek_common.h>
|
||||
#include "ecryptfs_kernel.h"
|
||||
|
||||
#define ECRYPTFS_DEK_XATTR_NAME "user.sdp"
|
||||
|
||||
#define ECRYPTFS_DEK_DEBUG 0
|
||||
|
||||
#define O_SDP 0x10000000
|
||||
|
||||
enum sdp_op {
|
||||
TO_SENSITIVE = 0,
|
||||
TO_PROTECTED
|
||||
};
|
||||
|
||||
int ecryptfs_super_block_get_userid(struct super_block *sb);
|
||||
int ecryptfs_is_sdp_locked(int engine_id);
|
||||
void ecryptfs_clean_sdp_dek(struct ecryptfs_crypt_stat *crypt_stat);
|
||||
int ecryptfs_get_sdp_dek(struct ecryptfs_crypt_stat *crypt_stat);
|
||||
int ecryptfs_sdp_convert_dek(struct dentry *dentry);
|
||||
int ecryptfs_parse_xattr_is_sensitive(const void *data, int len);
|
||||
|
||||
int write_dek_packet(char *dest, struct ecryptfs_crypt_stat *crypt_stat, size_t *written);
|
||||
int parse_dek_packet(char *data, struct ecryptfs_crypt_stat *crypt_stat, size_t *packet_size);
|
||||
|
||||
long ecryptfs_do_sdp_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
|
||||
int ecryptfs_sdp_set_sensitive(int engine_id, struct dentry *dentry);
|
||||
int ecryptfs_sdp_set_protected(struct dentry *dentry);
|
||||
void ecryptfs_set_mapping_sensitive(struct inode *ecryptfs_inode, int userid, enum sdp_op operation);
|
||||
|
||||
void ecryptfs_fs_request_callback(int opcode, int ret, unsigned long ino);
|
||||
|
||||
#define ECRYPTFS_EVT_RENAME_TO_CHAMBER 1
|
||||
#define ECRYPTFS_EVT_RENAME_OUT_OF_CHAMBER 2
|
||||
|
||||
/*
|
||||
* ioctl for SDP
|
||||
*/
|
||||
|
||||
typedef struct _dek_arg_sdp_info {
|
||||
int engine_id;
|
||||
int sdp_enabled;
|
||||
int is_sensitive;
|
||||
int is_chamber;
|
||||
unsigned int type;
|
||||
}dek_arg_get_sdp_info;
|
||||
|
||||
typedef struct _dek_arg_set_sensitive {
|
||||
int engine_id;
|
||||
}dek_arg_set_sensitive;
|
||||
|
||||
typedef struct _dek_arg_add_chamber {
|
||||
int engine_id;
|
||||
}dek_arg_add_chamber;
|
||||
|
||||
#define ECRYPTFS_IOCTL_GET_SDP_INFO _IOR('l', 0x11, __u32)
|
||||
#define ECRYPTFS_IOCTL_SET_SENSITIVE _IOW('l', 0x15, __u32)
|
||||
#define ECRYPTFS_IOCTL_SET_PROTECTED _IOW('l', 0x16, __u32)
|
||||
#define ECRYPTFS_IOCTL_ADD_CHAMBER _IOW('l', 0x17, __u32)
|
||||
#define ECRYPTFS_IOCTL_REMOVE_CHAMBER _IOW('l', 0x18, __u32)
|
||||
|
||||
#endif /* #ifndef ECRYPTFS_DEK_H */
|
|
@ -40,11 +40,6 @@
|
|||
#include <linux/nsproxy.h>
|
||||
#include <linux/backing-dev.h>
|
||||
#include <linux/ecryptfs.h>
|
||||
#ifdef CONFIG_SDP
|
||||
#include <sdp/dek_common.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/spinlock.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_WTL_ENCRYPTION_FILTER
|
||||
#define ENC_NAME_FILTER_MAX_INSTANCE 5
|
||||
|
@ -66,10 +61,6 @@
|
|||
#define ECRYPTFS_BASE_PATH_SIZE 1024
|
||||
#define ECRYPTFS_LABEL_SIZE 1024
|
||||
|
||||
#ifdef CONFIG_SDP
|
||||
#define PKG_NAME_SIZE 16
|
||||
#endif
|
||||
|
||||
void ecryptfs_dump_auth_tok(struct ecryptfs_auth_tok *auth_tok);
|
||||
extern void ecryptfs_to_hex(char *dst, char *src, size_t src_size);
|
||||
extern void ecryptfs_from_hex(char *dst, char *src, int dst_size);
|
||||
|
@ -244,12 +235,6 @@ struct ecryptfs_crypt_stat {
|
|||
#define ECRYPTFS_I_SIZE_INITIALIZED 0x00004000
|
||||
#ifdef CONFIG_WTL_ENCRYPTION_FILTER
|
||||
#define ECRYPTFS_ENCRYPTED_OTHER_DEVICE 0x00008000
|
||||
#endif
|
||||
#ifdef CONFIG_SDP
|
||||
#define ECRYPTFS_DEK_SDP_ENABLED 0x00100000
|
||||
#define ECRYPTFS_DEK_IS_SENSITIVE 0x00200000
|
||||
#define ECRYPTFS_DEK_MULTI_ENGINE 0x00400000 // eCryptfs header contains engine id.
|
||||
#define ECRYPTFS_SDP_IS_CHAMBER_DIR 0x02000000
|
||||
#endif
|
||||
|
||||
u32 flags;
|
||||
|
@ -272,10 +257,6 @@ struct ecryptfs_crypt_stat {
|
|||
struct mutex cs_tfm_mutex;
|
||||
struct mutex cs_hash_tfm_mutex;
|
||||
struct mutex cs_mutex;
|
||||
#ifdef CONFIG_SDP
|
||||
int engine_id;
|
||||
dek_t sdp_dek;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* inode private data. */
|
||||
|
@ -372,9 +353,6 @@ struct ecryptfs_mount_crypt_stat {
|
|||
#endif
|
||||
#if defined(CONFIG_CRYPTO_FIPS) && !defined(CONFIG_FORCE_DISABLE_FIPS)
|
||||
#define ECRYPTFS_ENABLE_CC 0x00000400
|
||||
#endif
|
||||
#ifdef CONFIG_SDP
|
||||
#define ECRYPTFS_MOUNT_SDP_ENABLED 0x80000000
|
||||
#endif
|
||||
|
||||
u32 flags;
|
||||
|
@ -394,13 +372,6 @@ struct ecryptfs_mount_crypt_stat {
|
|||
char enc_filter_ext[ENC_EXT_FILTER_MAX_INSTANCE]
|
||||
[ENC_EXT_FILTER_MAX_LEN + 1];
|
||||
#endif
|
||||
#ifdef CONFIG_SDP
|
||||
int userid;
|
||||
struct list_head chamber_dir_list;
|
||||
spinlock_t chamber_dir_list_lock;
|
||||
int partition_id;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#define ECRYPTFS_OVERRIDE_ROOT_CRED(saved_cred) \
|
||||
|
@ -428,9 +399,6 @@ struct ecryptfs_sb_info {
|
|||
struct ecryptfs_mount_crypt_stat mount_crypt_stat;
|
||||
struct backing_dev_info bdi;
|
||||
struct ecryptfs_propagate_stat propagate_stat;
|
||||
#ifdef CONFIG_SDP
|
||||
int userid;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* file private data. */
|
||||
|
|
|
@ -1,183 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Sensitive Data Protection
|
||||
*
|
||||
* 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 <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "ecryptfs_sdp_chamber.h"
|
||||
|
||||
#include <sdp/common.h>
|
||||
|
||||
#define CHAMBER_PATH_MAX 512
|
||||
typedef struct __chamber_info {
|
||||
int partition_id;
|
||||
int engine_id;
|
||||
|
||||
struct list_head list;
|
||||
char path[CHAMBER_PATH_MAX];
|
||||
}chamber_info_t;
|
||||
|
||||
#define NO_DIRECTORY_SEPARATOR_IN_CHAMBER_PATH 1
|
||||
/* Debug */
|
||||
#define CHAMBER_DEBUG 0
|
||||
|
||||
#if CHAMBER_DEBUG
|
||||
#define CHAMBER_LOGD(FMT, ...) printk("SDP_CHAMBER[%d] %s :: " FMT , current->pid, __func__, ##__VA_ARGS__)
|
||||
#else
|
||||
#define CHAMBER_LOGD(FMT, ...)
|
||||
#endif /* PUB_CRYPTO_DEBUG */
|
||||
#define CHAMBER_LOGE(FMT, ...) printk("SDP_CHAMBER[%d] %s :: " FMT , current->pid, __func__, ##__VA_ARGS__)
|
||||
|
||||
|
||||
chamber_info_t *alloc_chamber_info(int partition_id, int engine_id, const unsigned char *path) {
|
||||
chamber_info_t *new_chamber = kmalloc(sizeof(chamber_info_t), GFP_KERNEL);
|
||||
|
||||
if(new_chamber == NULL) {
|
||||
CHAMBER_LOGE("can't alloc memory for chamber_info\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
new_chamber->partition_id = partition_id;
|
||||
new_chamber->engine_id = engine_id;
|
||||
snprintf(new_chamber->path, CHAMBER_PATH_MAX, "%s", path);
|
||||
|
||||
return new_chamber;
|
||||
}
|
||||
|
||||
int add_chamber_directory(struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
|
||||
int engine_id, const unsigned char *path) {
|
||||
chamber_info_t *new_chamber = NULL;
|
||||
|
||||
#if NO_DIRECTORY_SEPARATOR_IN_CHAMBER_PATH
|
||||
if(strchr(path, '/') != NULL) {
|
||||
CHAMBER_LOGE("Chamber directory cannot contain '/'\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
new_chamber = alloc_chamber_info(mount_crypt_stat->partition_id, engine_id, path);
|
||||
|
||||
if(new_chamber == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
spin_lock(&(mount_crypt_stat->chamber_dir_list_lock));
|
||||
CHAMBER_LOGD("Adding %s into chamber list\n", new_chamber->path);
|
||||
list_add_tail(&new_chamber->list, &(mount_crypt_stat->chamber_dir_list));
|
||||
spin_unlock(&(mount_crypt_stat->chamber_dir_list_lock));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
chamber_info_t *find_chamber_info(struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
|
||||
const unsigned char *path) {
|
||||
struct list_head *entry;
|
||||
|
||||
spin_lock(&(mount_crypt_stat->chamber_dir_list_lock));
|
||||
|
||||
CHAMBER_LOGD("%s\n", path);
|
||||
|
||||
list_for_each(entry, &mount_crypt_stat->chamber_dir_list) {
|
||||
chamber_info_t *info;
|
||||
info = list_entry(entry, chamber_info_t, list);
|
||||
|
||||
// Check path
|
||||
if(!strncmp(path, info->path, CHAMBER_PATH_MAX)) {
|
||||
CHAMBER_LOGD("Found %s from chamber list\n", info->path);
|
||||
|
||||
spin_unlock(&(mount_crypt_stat->chamber_dir_list_lock));
|
||||
return info;
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock(&(mount_crypt_stat->chamber_dir_list_lock));
|
||||
CHAMBER_LOGD("Not found\n");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void del_chamber_directory(struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
|
||||
const unsigned char *path) {
|
||||
chamber_info_t *info = find_chamber_info(mount_crypt_stat, path);
|
||||
if(info == NULL) {
|
||||
CHAMBER_LOGD("nothing to remove\n");
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock(&mount_crypt_stat->chamber_dir_list_lock);
|
||||
CHAMBER_LOGD("%s removed\n", info->path);
|
||||
list_del(&info->list);
|
||||
|
||||
kfree(info);
|
||||
spin_unlock(&mount_crypt_stat->chamber_dir_list_lock);
|
||||
}
|
||||
|
||||
int is_chamber_directory(struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
|
||||
const unsigned char *path, int *engineid) {
|
||||
chamber_info_t *info;
|
||||
#if NO_DIRECTORY_SEPARATOR_IN_CHAMBER_PATH
|
||||
if(strchr(path, '/') != NULL) {
|
||||
CHAMBER_LOGD("%s containes '/'\n", path);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
info = find_chamber_info(mount_crypt_stat, path);
|
||||
if(info == NULL)
|
||||
return 0;
|
||||
|
||||
if(engineid) *engineid = info->engine_id;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void set_chamber_flag(int engineid, struct inode *inode) {
|
||||
struct ecryptfs_crypt_stat *crypt_stat;
|
||||
|
||||
if(inode == NULL) {
|
||||
CHAMBER_LOGE("invalid inode\n");
|
||||
return;
|
||||
}
|
||||
|
||||
crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
|
||||
|
||||
crypt_stat->engine_id = engineid;
|
||||
crypt_stat->flags |= ECRYPTFS_SDP_IS_CHAMBER_DIR;
|
||||
crypt_stat->flags |= ECRYPTFS_DEK_IS_SENSITIVE;
|
||||
}
|
||||
|
||||
void clr_chamber_flag(struct inode *inode) {
|
||||
struct ecryptfs_crypt_stat *crypt_stat;
|
||||
|
||||
if(inode == NULL) {
|
||||
CHAMBER_LOGE("invalid inode\n");
|
||||
return;
|
||||
}
|
||||
|
||||
crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
|
||||
|
||||
crypt_stat->engine_id = -1;
|
||||
crypt_stat->flags &= ~ECRYPTFS_DEK_IS_SENSITIVE;
|
||||
crypt_stat->flags &= ~ECRYPTFS_SDP_IS_CHAMBER_DIR;
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Sensitive Data Protection
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef ECRYPTFS_SDP_CHAMBER_H_
|
||||
#define ECRYPTFS_SDP_CHAMBER_H_
|
||||
|
||||
#include "ecryptfs_kernel.h"
|
||||
|
||||
int add_chamber_directory(struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
|
||||
int engine_id, const unsigned char *path);
|
||||
void del_chamber_directory(struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
|
||||
const unsigned char *path);
|
||||
int is_chamber_directory(struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
|
||||
const unsigned char *path, int *engineid);
|
||||
|
||||
void set_chamber_flag(int engineid, struct inode *inode);
|
||||
void clr_chamber_flag(struct inode *inode);
|
||||
|
||||
#define IS_UNDER_ROOT(dentry) (dentry->d_parent->d_inode == dentry->d_sb->s_root->d_inode)
|
||||
#define IS_CHAMBER_DENTRY(dentry) (ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat.flags & ECRYPTFS_SDP_IS_CHAMBER_DIR)
|
||||
#define IS_SENSITIVE_DENTRY(dentry) (ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat.flags & ECRYPTFS_DEK_IS_SENSITIVE)
|
||||
|
||||
#endif /* ECRYPTFS_SDP_CHAMBER_H_ */
|
|
@ -39,15 +39,6 @@
|
|||
#define ECRYPTFS_WAS_ENCRYPTED 0x0080
|
||||
#define ECRYPTFS_WAS_ENCRYPTED_OTHER_DEVICE 0x0100
|
||||
#endif
|
||||
#ifdef CONFIG_SDP
|
||||
#if 0
|
||||
#include <linux/fs.h>
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/atomic.h>
|
||||
#endif
|
||||
#include "ecryptfs_dek.h"
|
||||
#include "mm.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* ecryptfs_read_update_atime
|
||||
|
@ -219,14 +210,6 @@ static int read_or_initialize_metadata(struct dentry *dentry)
|
|||
if (!rc)
|
||||
goto out;
|
||||
|
||||
#ifdef CONFIG_SDP
|
||||
/*
|
||||
* no passthrough/xattr for sensitive files
|
||||
*/
|
||||
if ((rc) && crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE)
|
||||
goto out;
|
||||
#endif
|
||||
|
||||
if (mount_crypt_stat->flags & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED) {
|
||||
crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED
|
||||
| ECRYPTFS_ENCRYPTED);
|
||||
|
@ -244,25 +227,6 @@ static int read_or_initialize_metadata(struct dentry *dentry)
|
|||
rc = -EIO;
|
||||
out:
|
||||
mutex_unlock(&crypt_stat->cs_mutex);
|
||||
#ifdef CONFIG_SDP
|
||||
if(!rc)
|
||||
{
|
||||
/*
|
||||
* SDP v2.0 : sensitive directory (SDP vault)
|
||||
* Files under sensitive directory automatically becomes sensitive
|
||||
*/
|
||||
struct dentry *p = dentry->d_parent;
|
||||
struct inode *parent_inode = p->d_inode;
|
||||
struct ecryptfs_crypt_stat *parent_crypt_stat =
|
||||
&ecryptfs_inode_to_private(parent_inode)->crypt_stat;
|
||||
|
||||
if (!(crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE) &&
|
||||
((S_ISDIR(parent_inode->i_mode)) &&
|
||||
(parent_crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE))) {
|
||||
rc = ecryptfs_sdp_set_sensitive(parent_crypt_stat->engine_id, dentry);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -347,13 +311,6 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
|
|||
ecryptfs_set_file_lower(
|
||||
file, ecryptfs_inode_to_private(inode)->lower_file);
|
||||
if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) {
|
||||
#ifdef CONFIG_SDP
|
||||
/*
|
||||
* it's possible to have a sensitive directory. (vault)
|
||||
*/
|
||||
if (mount_crypt_stat->flags & ECRYPTFS_MOUNT_SDP_ENABLED)
|
||||
crypt_stat->flags |= ECRYPTFS_DEK_SDP_ENABLED;
|
||||
#endif
|
||||
ecryptfs_printk(KERN_DEBUG, "This is a directory\n");
|
||||
mutex_lock(&crypt_stat->cs_mutex);
|
||||
crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
|
||||
|
@ -363,63 +320,8 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
|
|||
}
|
||||
rc = read_or_initialize_metadata(ecryptfs_dentry);
|
||||
if (rc) {
|
||||
#ifdef CONFIG_SDP
|
||||
if(file->f_flags & O_SDP){
|
||||
printk("Failed to initialize metadata, "
|
||||
"but let it continue cause current call is from SDP API\n");
|
||||
mutex_lock(&crypt_stat->cs_mutex);
|
||||
crypt_stat->flags &= ~(ECRYPTFS_KEY_VALID);
|
||||
mutex_unlock(&crypt_stat->cs_mutex);
|
||||
rc = 0;
|
||||
/*
|
||||
* Letting this continue doesn't mean to allow read/writing. It will anyway fail later.
|
||||
*
|
||||
* 1. In this stage, ecryptfs_stat won't have key/iv and encryption ctx.
|
||||
* 2. ECRYPTFS_KEY_VALID bit is off, next attempt will try reading metadata again.
|
||||
* 3. Skip DEK conversion. it cannot be done anyway.
|
||||
*/
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
goto out_put;
|
||||
}
|
||||
#ifdef CONFIG_SDP
|
||||
if (crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE) {
|
||||
#ifdef CONFIG_SDP_KEY_DUMP
|
||||
if (S_ISREG(ecryptfs_dentry->d_inode->i_mode)) {
|
||||
if(get_sdp_sysfs_key_dump()) {
|
||||
printk("FEK[%s] : ", ecryptfs_dentry->d_name.name);
|
||||
key_dump(crypt_stat->key, 32);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* Need to update sensitive mapping on file open
|
||||
*/
|
||||
if (S_ISREG(ecryptfs_dentry->d_inode->i_mode)) {
|
||||
ecryptfs_set_mapping_sensitive(inode, mount_crypt_stat->userid, TO_SENSITIVE);
|
||||
}
|
||||
|
||||
if (ecryptfs_is_sdp_locked(crypt_stat->engine_id)) {
|
||||
ecryptfs_printk(KERN_INFO, "ecryptfs_open: persona is locked, rc=%d\n", rc);
|
||||
} else {
|
||||
int dek_type = crypt_stat->sdp_dek.type;
|
||||
|
||||
ecryptfs_printk(KERN_INFO, "ecryptfs_open: persona is unlocked, rc=%d\n", rc);
|
||||
if(dek_type != DEK_TYPE_AES_ENC) {
|
||||
ecryptfs_printk(KERN_DEBUG, "converting dek...\n");
|
||||
rc = ecryptfs_sdp_convert_dek(ecryptfs_dentry);
|
||||
ecryptfs_printk(KERN_DEBUG, "conversion ready, rc=%d\n", rc);
|
||||
rc = 0; // TODO: Do we need to return error if conversion fails?
|
||||
}
|
||||
}
|
||||
}
|
||||
#if ECRYPTFS_DEK_DEBUG
|
||||
else {
|
||||
ecryptfs_printk(KERN_INFO, "ecryptfs_open: dek_file_type is protected\n");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
ecryptfs_printk(KERN_DEBUG, "inode w/ addr = [0x%p], i_ino = "
|
||||
"[0x%.16lx] size: [0x%.16llx]\n", inode, inode->i_ino,
|
||||
|
@ -451,13 +353,7 @@ static int ecryptfs_release(struct inode *inode, struct file *file)
|
|||
struct ecryptfs_crypt_stat *crypt_stat;
|
||||
crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
|
||||
|
||||
#ifdef CONFIG_SDP
|
||||
mutex_lock(&crypt_stat->cs_mutex);
|
||||
#endif
|
||||
ecryptfs_put_lower_file(inode);
|
||||
#ifdef CONFIG_SDP
|
||||
mutex_unlock(&crypt_stat->cs_mutex);
|
||||
#endif
|
||||
kmem_cache_free(ecryptfs_file_info_cache,
|
||||
ecryptfs_file_to_private(file));
|
||||
return 0;
|
||||
|
@ -524,13 +420,6 @@ ecryptfs_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SDP
|
||||
rc = ecryptfs_do_sdp_ioctl(file, cmd, arg);
|
||||
if (rc != EOPNOTSUPP)
|
||||
return rc;
|
||||
#else
|
||||
printk("%s CONFIG_SDP not enabled \n", __func__);
|
||||
#endif
|
||||
if (ecryptfs_file_to_private(file))
|
||||
lower_file = ecryptfs_file_to_lower(file);
|
||||
if (lower_file && lower_file->f_op && lower_file->f_op->unlocked_ioctl)
|
||||
|
@ -545,14 +434,6 @@ ecryptfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
struct file *lower_file = NULL;
|
||||
long rc = -ENOIOCTLCMD;
|
||||
|
||||
#ifdef CONFIG_SDP
|
||||
rc = ecryptfs_do_sdp_ioctl(file, cmd, arg);
|
||||
if (rc != EOPNOTSUPP)
|
||||
return rc;
|
||||
#else
|
||||
printk("%s CONFIG_SDP not enabled \n", __func__);
|
||||
#endif
|
||||
|
||||
if (ecryptfs_file_to_private(file))
|
||||
lower_file = ecryptfs_file_to_lower(file);
|
||||
if (lower_file && lower_file->f_op && lower_file->f_op->compat_ioctl)
|
||||
|
|
|
@ -36,14 +36,6 @@
|
|||
#include <asm/unaligned.h>
|
||||
#include "ecryptfs_kernel.h"
|
||||
|
||||
#ifdef CONFIG_SDP
|
||||
#include <sdp/fs_request.h>
|
||||
#include "ecryptfs_sdp_chamber.h"
|
||||
#include "ecryptfs_dek.h"
|
||||
|
||||
#include "../sdcardfs/sdcardfs.h"
|
||||
#endif
|
||||
|
||||
/* Do not directly use this function. Use ECRYPTFS_OVERRIDE_CRED() instead. */
|
||||
const struct cred * ecryptfs_override_fsids(uid_t fsuid, gid_t fsgid)
|
||||
{
|
||||
|
@ -72,7 +64,6 @@ void ecryptfs_revert_fsids(const struct cred * old_cred)
|
|||
put_cred(cur_cred);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SDP
|
||||
static struct dentry *lock_parent(struct dentry *dentry)
|
||||
{
|
||||
struct dentry *dir;
|
||||
|
@ -87,7 +78,6 @@ static void unlock_dir(struct dentry *dir)
|
|||
mutex_unlock(&dir->d_inode->i_mutex);
|
||||
dput(dir);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int ecryptfs_inode_test(struct inode *inode, void *lower_inode)
|
||||
{
|
||||
|
@ -181,36 +171,6 @@ static int ecryptfs_interpose(struct dentry *lower_dentry,
|
|||
if(d_unhashed(dentry))
|
||||
d_rehash(dentry);
|
||||
|
||||
#ifdef CONFIG_SDP
|
||||
if(S_ISDIR(inode->i_mode) && dentry) {
|
||||
if(IS_UNDER_ROOT(dentry)) {
|
||||
struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
|
||||
&ecryptfs_superblock_to_private(inode->i_sb)->mount_crypt_stat;
|
||||
int engineid;
|
||||
printk("Creating a directoy under root directory of current partition.\n");
|
||||
|
||||
if(is_chamber_directory(mount_crypt_stat, dentry->d_name.name, &engineid)) {
|
||||
printk("This is a chamber directory engine[%d]\n", engineid);
|
||||
set_chamber_flag(engineid, inode);
|
||||
}
|
||||
} else if(IS_SENSITIVE_DENTRY(dentry->d_parent)) {
|
||||
/*
|
||||
* When parent directory is sensitive
|
||||
*/
|
||||
struct ecryptfs_crypt_stat *crypt_stat =
|
||||
&ecryptfs_inode_to_private(inode)->crypt_stat;
|
||||
struct ecryptfs_crypt_stat *parent_crypt_stat =
|
||||
&ecryptfs_inode_to_private(dentry->d_parent->d_inode)->crypt_stat;
|
||||
|
||||
//TODO : remove this log
|
||||
DEK_LOGE("Parent %s[id:%d] is sensitive. so this directory is sensitive too\n",
|
||||
dentry->d_parent->d_name.name, parent_crypt_stat->engine_id);
|
||||
crypt_stat->flags |= ECRYPTFS_DEK_IS_SENSITIVE;
|
||||
crypt_stat->engine_id = parent_crypt_stat->engine_id;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -581,38 +541,6 @@ static int ecryptfs_lookup_interpose(struct dentry *dentry,
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SDP
|
||||
if (S_ISDIR(inode->i_mode) && dentry) {
|
||||
if(IS_UNDER_ROOT(dentry)) {
|
||||
struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
|
||||
&ecryptfs_superblock_to_private(inode->i_sb)->mount_crypt_stat;
|
||||
int engineid;
|
||||
printk("Lookup a directoy under root directory of current partition.\n");
|
||||
|
||||
if(is_chamber_directory(mount_crypt_stat, dentry->d_name.name, &engineid)) {
|
||||
/*
|
||||
* When this directory is under ROOT directory and the name is registered
|
||||
* as Chamber.
|
||||
*/
|
||||
printk("This is a chamber directory engine[%d]\n", engineid);
|
||||
set_chamber_flag(engineid, inode);
|
||||
}
|
||||
} else if(IS_SENSITIVE_DENTRY(dentry->d_parent)) {
|
||||
/*
|
||||
* When parent directory is sensitive
|
||||
*/
|
||||
struct ecryptfs_crypt_stat *crypt_stat =
|
||||
&ecryptfs_inode_to_private(inode)->crypt_stat;
|
||||
struct ecryptfs_crypt_stat *parent_crypt_stat =
|
||||
&ecryptfs_inode_to_private(dentry->d_parent->d_inode)->crypt_stat;
|
||||
printk("Parent %s is sensitive. so this directory is sensitive too\n",
|
||||
dentry->d_parent->d_name.name);
|
||||
crypt_stat->flags |= ECRYPTFS_DEK_IS_SENSITIVE;
|
||||
crypt_stat->engine_id = parent_crypt_stat->engine_id;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (inode->i_state & I_NEW)
|
||||
unlock_new_inode(inode);
|
||||
d_add(dentry, inode);
|
||||
|
@ -620,13 +548,6 @@ static int ecryptfs_lookup_interpose(struct dentry *dentry,
|
|||
return rc;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SDP
|
||||
static inline int isdigit(int ch)
|
||||
{
|
||||
return (ch >= '0') && (ch <= '9');
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* ecryptfs_lookup
|
||||
* @ecryptfs_dir_inode: The eCryptfs directory inode
|
||||
|
@ -684,68 +605,9 @@ static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode,
|
|||
}
|
||||
mutex_lock(&lower_dir_dentry->d_inode->i_mutex);
|
||||
|
||||
#ifdef CONFIG_SDP
|
||||
if(!strncmp(lower_dir_dentry->d_sb->s_type->name, "sdcardfs", 8)) {
|
||||
struct sdcardfs_dentry_info *dinfo = SDCARDFS_D(lower_dir_dentry);
|
||||
struct dentry *parent = dget_parent(lower_dir_dentry);
|
||||
struct sdcardfs_dentry_info *parent_info = SDCARDFS_D(parent);
|
||||
|
||||
dinfo->under_knox = 1;
|
||||
dinfo->userid = -1;
|
||||
|
||||
if(IS_UNDER_ROOT(ecryptfs_dentry)) {
|
||||
parent_info->permission = PERMISSION_PRE_ROOT;
|
||||
if(mount_crypt_stat->userid >= 100 && mount_crypt_stat->userid <= 200) {
|
||||
parent_info->userid = mount_crypt_stat->userid;
|
||||
|
||||
/* Assume masked off by default. */
|
||||
if (!strcasecmp(ecryptfs_dentry->d_name.name, "Android")) {
|
||||
/* App-specific directories inside; let anyone traverse */
|
||||
dinfo->permission = PERMISSION_ROOT;
|
||||
}
|
||||
}
|
||||
else {
|
||||
int len = strlen(ecryptfs_dentry->d_name.name);
|
||||
int i, numeric = 1;
|
||||
|
||||
for(i=0 ; i < len ; i++)
|
||||
if(!isdigit(ecryptfs_dentry->d_name.name[i])) { numeric = 0; break; }
|
||||
if(numeric) {
|
||||
dinfo->userid = simple_strtoul(ecryptfs_dentry->d_name.name, NULL, 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
struct sdcardfs_sb_info *sbi = SDCARDFS_SB(lower_dir_dentry->d_sb);
|
||||
|
||||
/* Derive custom permissions based on parent and current node */
|
||||
switch (parent_info->permission) {
|
||||
case PERMISSION_ROOT:
|
||||
if (!strcasecmp(ecryptfs_dentry->d_name.name, "data") || !strcasecmp(ecryptfs_dentry->d_name.name, "obb") || !strcasecmp(ecryptfs_dentry->d_name.name, "media")) {
|
||||
/* App-specific directories inside; let anyone traverse */
|
||||
dinfo->permission = PERMISSION_ANDROID;
|
||||
}
|
||||
break;
|
||||
case PERMISSION_ANDROID:
|
||||
dinfo->permission = PERMISSION_UNDER_ANDROID;
|
||||
dinfo->appid = get_appid(sbi->pkgl_id, ecryptfs_dentry->d_name.name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
dput(parent);
|
||||
}
|
||||
#endif
|
||||
|
||||
lower_dentry = lookup_one_len(encrypted_and_encoded_name,
|
||||
lower_dir_dentry,
|
||||
encrypted_and_encoded_name_size);
|
||||
#ifdef CONFIG_SDP
|
||||
if(!strncmp(lower_dir_dentry->d_sb->s_type->name, "sdcardfs", 8)) {
|
||||
struct sdcardfs_dentry_info *dinfo = SDCARDFS_D(lower_dir_dentry);
|
||||
dinfo->under_knox = 0;
|
||||
dinfo->userid = -1;
|
||||
}
|
||||
#endif
|
||||
mutex_unlock(&lower_dir_dentry->d_inode->i_mutex);
|
||||
if (IS_ERR(lower_dentry)) {
|
||||
rc = PTR_ERR(lower_dentry);
|
||||
|
@ -853,23 +715,6 @@ static int ecryptfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
|
|||
lower_dentry = ecryptfs_dentry_to_lower(dentry);
|
||||
lower_dir_dentry = lock_parent(lower_dentry);
|
||||
|
||||
#ifdef CONFIG_SDP
|
||||
if(!strncmp(lower_dir_dentry->d_sb->s_type->name, "sdcardfs", 8)) {
|
||||
struct sdcardfs_dentry_info *dinfo = SDCARDFS_D(lower_dir_dentry);
|
||||
int len = strlen(dentry->d_name.name);
|
||||
int i, numeric = 1;
|
||||
|
||||
dinfo->under_knox = 1;
|
||||
dinfo->userid = -1;
|
||||
if(IS_UNDER_ROOT(dentry)) {
|
||||
for(i=0 ; i < len ; i++)
|
||||
if(!isdigit(dentry->d_name.name[i])) { numeric = 0; break; }
|
||||
if(numeric) {
|
||||
dinfo->userid = simple_strtoul(dentry->d_name.name, NULL, 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
rc = vfs_mkdir(lower_dir_dentry->d_inode, lower_dentry, mode);
|
||||
if (rc || !lower_dentry->d_inode)
|
||||
goto out;
|
||||
|
@ -880,13 +725,6 @@ static int ecryptfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
|
|||
fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode);
|
||||
set_nlink(dir, lower_dir_dentry->d_inode->i_nlink);
|
||||
out:
|
||||
#ifdef CONFIG_SDP
|
||||
if(!strncmp(lower_dir_dentry->d_sb->s_type->name, "sdcardfs", 8)) {
|
||||
struct sdcardfs_dentry_info *dinfo = SDCARDFS_D(lower_dir_dentry);
|
||||
dinfo->under_knox = 0;
|
||||
dinfo->userid = -1;
|
||||
}
|
||||
#endif
|
||||
unlock_dir(lower_dir_dentry);
|
||||
if (!dentry->d_inode)
|
||||
d_drop(dentry);
|
||||
|
@ -899,13 +737,6 @@ static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry)
|
|||
struct dentry *lower_dir_dentry;
|
||||
int rc;
|
||||
|
||||
#ifdef CONFIG_SDP
|
||||
if(IS_CHAMBER_DENTRY(dentry)) {
|
||||
printk("You're removing chamber directory. I/O error\n");
|
||||
return -EIO;
|
||||
}
|
||||
#endif
|
||||
|
||||
lower_dentry = ecryptfs_dentry_to_lower(dentry);
|
||||
dget(dentry);
|
||||
lower_dir_dentry = lock_parent(lower_dentry);
|
||||
|
@ -947,8 +778,6 @@ out:
|
|||
return rc;
|
||||
}
|
||||
|
||||
#define ECRYPTFS_SDP_RENAME_DEBUG 0
|
||||
|
||||
static int
|
||||
ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||
struct inode *new_dir, struct dentry *new_dentry)
|
||||
|
@ -960,72 +789,6 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
|||
struct dentry *lower_new_dir_dentry;
|
||||
struct dentry *trap = NULL;
|
||||
struct inode *target_inode;
|
||||
#ifdef CONFIG_SDP
|
||||
sdp_fs_command_t *cmd = NULL;
|
||||
int rename_event = 0x00;
|
||||
struct ecryptfs_crypt_stat *crypt_stat =
|
||||
&(ecryptfs_inode_to_private(old_dentry->d_inode)->crypt_stat);
|
||||
struct ecryptfs_crypt_stat *parent_crypt_stat =
|
||||
&(ecryptfs_inode_to_private(old_dentry->d_parent->d_inode)->crypt_stat);
|
||||
struct ecryptfs_crypt_stat *new_parent_crypt_stat =
|
||||
&(ecryptfs_inode_to_private(new_dentry->d_parent->d_inode)->crypt_stat);
|
||||
struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
|
||||
&ecryptfs_superblock_to_private(old_dentry->d_sb)->mount_crypt_stat;
|
||||
|
||||
#if ECRYPTFS_SDP_RENAME_DEBUG
|
||||
printk("You're renaming %s to %s\n",
|
||||
old_dentry->d_name.name,
|
||||
new_dentry->d_name.name);
|
||||
printk("old_dentry[%p] : %s [parent %s : %s] inode:%p\n",
|
||||
old_dentry, old_dentry->d_name.name,
|
||||
old_dentry->d_parent->d_name.name,
|
||||
IS_SENSITIVE_DENTRY(old_dentry->d_parent) ? "sensitive" : "protected",
|
||||
old_dentry->d_inode);
|
||||
printk("new_dentry[%p] : %s [parent %s : %s] inode:%p\n",
|
||||
new_dentry, new_dentry->d_name.name,
|
||||
new_dentry->d_parent->d_name.name,
|
||||
IS_SENSITIVE_DENTRY(new_dentry->d_parent) ? "sensitive" : "protected",
|
||||
new_dentry->d_inode);
|
||||
#endif
|
||||
|
||||
if(IS_CHAMBER_DENTRY(old_dentry)) {
|
||||
printk("Rename trial on chamber : failed\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
#if 0 // kernel panic. new_crypt_stat->engine_id
|
||||
if(IS_SENSITIVE_DENTRY(old_dentry->d_parent) &&
|
||||
IS_SENSITIVE_DENTRY(new_dentry->d_parent)) {
|
||||
if(crypt_stat->engine_id != new_crypt_stat->engine_id) {
|
||||
printk("Rename chamber file to another chamber : failed\n");
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if(IS_SENSITIVE_DENTRY(old_dentry->d_parent)) {
|
||||
if(ecryptfs_is_sdp_locked(parent_crypt_stat->engine_id)) {
|
||||
printk("Rename/move trial in locked state\n");
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
if(IS_SENSITIVE_DENTRY(old_dentry->d_parent) &&
|
||||
IS_SENSITIVE_DENTRY(new_dentry->d_parent)) {
|
||||
if(parent_crypt_stat->engine_id != new_parent_crypt_stat->engine_id) {
|
||||
printk("Can't move between chambers\n");
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
if(IS_SENSITIVE_DENTRY(old_dentry->d_parent) &&
|
||||
!IS_SENSITIVE_DENTRY(new_dentry->d_parent))
|
||||
rename_event |= ECRYPTFS_EVT_RENAME_OUT_OF_CHAMBER;
|
||||
|
||||
if(!IS_SENSITIVE_DENTRY(old_dentry->d_parent) &&
|
||||
IS_SENSITIVE_DENTRY(new_dentry->d_parent))
|
||||
rename_event |= ECRYPTFS_EVT_RENAME_TO_CHAMBER;
|
||||
#endif
|
||||
|
||||
lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry);
|
||||
lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry);
|
||||
|
@ -1056,45 +819,6 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
|||
if (new_dir != old_dir)
|
||||
fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode);
|
||||
|
||||
#ifdef CONFIG_SDP
|
||||
if(!rc) {
|
||||
crypt_stat = &(ecryptfs_inode_to_private(old_dentry->d_inode)->crypt_stat);
|
||||
|
||||
if(rename_event > 0) {
|
||||
switch(rename_event) {
|
||||
case ECRYPTFS_EVT_RENAME_TO_CHAMBER:
|
||||
cmd = sdp_fs_command_alloc(FSOP_SDP_SET_SENSITIVE, current->pid,
|
||||
mount_crypt_stat->userid, mount_crypt_stat->partition_id,
|
||||
old_dentry->d_inode->i_ino,
|
||||
GFP_NOFS);
|
||||
break;
|
||||
case ECRYPTFS_EVT_RENAME_OUT_OF_CHAMBER:
|
||||
cmd = sdp_fs_command_alloc(FSOP_SDP_SET_PROTECTED, current->pid,
|
||||
mount_crypt_stat->userid, mount_crypt_stat->partition_id,
|
||||
old_dentry->d_inode->i_ino,
|
||||
GFP_NOFS);
|
||||
break;
|
||||
default:
|
||||
cmd = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#if ECRYPTFS_SDP_RENAME_DEBUG
|
||||
printk("[end of rename] old_dentry[%p] : %s [parent %s : %s] inode:%p\n",
|
||||
old_dentry, old_dentry->d_name.name,
|
||||
old_dentry->d_parent->d_name.name,
|
||||
IS_SENSITIVE_DENTRY(old_dentry->d_parent) ? "sensitive" : "protected",
|
||||
old_dentry->d_inode);
|
||||
printk("[end of rename] new_dentry[%p] : %s [parent %s : %s] inode:%p\n",
|
||||
new_dentry, new_dentry->d_name.name,
|
||||
new_dentry->d_parent->d_name.name,
|
||||
IS_SENSITIVE_DENTRY(new_dentry->d_parent) ? "sensitive" : "protected",
|
||||
new_dentry->d_inode);
|
||||
#endif
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
out_lock:
|
||||
unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
|
||||
dput(lower_new_dir_dentry);
|
||||
|
@ -1102,12 +826,6 @@ out_lock:
|
|||
dput(lower_new_dentry);
|
||||
dput(lower_old_dentry);
|
||||
|
||||
#ifdef CONFIG_SDP
|
||||
if(!rc && cmd != NULL) {
|
||||
sdp_fs_request(cmd, ecryptfs_fs_request_callback);
|
||||
sdp_fs_command_free(cmd);
|
||||
}
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
|
@ -35,10 +35,6 @@
|
|||
#include <linux/slab.h>
|
||||
#include "ecryptfs_kernel.h"
|
||||
|
||||
#ifdef CONFIG_SDP
|
||||
#include "ecryptfs_dek.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* request_key returned an error instead of a valid key address;
|
||||
* determine the type of error, make appropriate log entries, and
|
||||
|
@ -1909,22 +1905,6 @@ int ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat,
|
|||
rc = -EIO;
|
||||
goto out_wipe_list;
|
||||
break;
|
||||
#ifdef CONFIG_SDP
|
||||
case ECRYPTFS_DEK_PACKET_TYPE:
|
||||
printk("%s() ECRYPTFS_DEK_PACKET_TYPE \n",
|
||||
__func__);
|
||||
rc = parse_dek_packet(
|
||||
(unsigned char *)&src[i], crypt_stat,
|
||||
&packet_size);
|
||||
if (rc) {
|
||||
ecryptfs_printk(KERN_ERR, "Error parsing "
|
||||
"dek packet %d\n", rc);
|
||||
rc = -EIO;
|
||||
goto out_wipe_list;
|
||||
}
|
||||
i += packet_size;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ecryptfs_printk(KERN_DEBUG, "No packet at offset [%zd] "
|
||||
"of the file header; hex value of "
|
||||
|
@ -2024,15 +2004,6 @@ found_matching_auth_tok:
|
|||
BUG();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SDP
|
||||
if((crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE)) {
|
||||
rc = ecryptfs_get_sdp_dek(crypt_stat);
|
||||
if (rc) {
|
||||
ecryptfs_printk(KERN_ERR, "Error setting sdp key after parse\n");
|
||||
goto out_wipe_list;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
rc = ecryptfs_compute_root_iv(crypt_stat);
|
||||
if (rc) {
|
||||
ecryptfs_printk(KERN_ERR, "Error computing "
|
||||
|
@ -2478,20 +2449,9 @@ encrypted_session_key_set:
|
|||
ECRYPTFS_SALT_SIZE);
|
||||
(*packet_size) += ECRYPTFS_SALT_SIZE; /* salt */
|
||||
dest[(*packet_size)++] = 0x60; /* hash iterations (65536) */
|
||||
#ifdef CONFIG_SDP
|
||||
if ((crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE)) {
|
||||
ecryptfs_printk(KERN_DEBUG, "Sensitive file, tag_3 to zeroes\n");
|
||||
memset(&dest[(*packet_size)], 0, key_rec->enc_key_size);
|
||||
} else {
|
||||
memcpy(&dest[(*packet_size)], key_rec->enc_key,
|
||||
key_rec->enc_key_size);
|
||||
}
|
||||
(*packet_size) += key_rec->enc_key_size;
|
||||
#else
|
||||
memcpy(&dest[(*packet_size)], key_rec->enc_key,
|
||||
key_rec->enc_key_size);
|
||||
(*packet_size) += key_rec->enc_key_size;
|
||||
#endif
|
||||
out:
|
||||
if (rc)
|
||||
(*packet_size) = 0;
|
||||
|
@ -2576,19 +2536,6 @@ ecryptfs_generate_key_packet_set(char *dest_base,
|
|||
goto out_free;
|
||||
}
|
||||
(*len) += written;
|
||||
#ifdef CONFIG_SDP
|
||||
if (crypt_stat->flags & ECRYPTFS_DEK_SDP_ENABLED &&
|
||||
crypt_stat->flags & ECRYPTFS_DEK_IS_SENSITIVE) {
|
||||
rc = write_dek_packet(dest_base + (*len), crypt_stat,
|
||||
&written);
|
||||
if (rc) {
|
||||
ecryptfs_printk(KERN_WARNING, "Error "
|
||||
"writing dek packet\n");
|
||||
goto out_free;
|
||||
}
|
||||
(*len) += written;
|
||||
}
|
||||
#endif
|
||||
} else if (auth_tok->token_type == ECRYPTFS_PRIVATE_KEY) {
|
||||
rc = write_tag_1_packet(dest_base + (*len), &max,
|
||||
auth_tok_key, auth_tok,
|
||||
|
|
|
@ -39,11 +39,6 @@
|
|||
#include <linux/magic.h>
|
||||
#include "ecryptfs_kernel.h"
|
||||
|
||||
#ifdef CONFIG_SDP
|
||||
#include "mm.h"
|
||||
#include "ecryptfs_sdp_chamber.h"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_WTL_ENCRYPTION_FILTER
|
||||
#include <linux/ctype.h>
|
||||
#endif
|
||||
|
@ -173,11 +168,6 @@ void ecryptfs_put_lower_file(struct inode *inode)
|
|||
if (atomic_dec_and_mutex_lock(&inode_info->lower_file_count,
|
||||
&inode_info->lower_file_mutex)) {
|
||||
filemap_write_and_wait(inode->i_mapping);
|
||||
#ifdef CONFIG_SDP
|
||||
if (inode_info->crypt_stat.flags & ECRYPTFS_DEK_IS_SENSITIVE) {
|
||||
ecryptfs_mm_do_sdp_cleanup(inode);
|
||||
}
|
||||
#endif
|
||||
fput(inode_info->lower_file);
|
||||
inode_info->lower_file = NULL;
|
||||
mutex_unlock(&inode_info->lower_file_mutex);
|
||||
|
@ -197,9 +187,6 @@ enum { ecryptfs_opt_sig, ecryptfs_opt_ecryptfs_sig,
|
|||
#endif
|
||||
#if defined(CONFIG_CRYPTO_FIPS) && !defined(CONFIG_FORCE_DISABLE_FIPS)
|
||||
ecryptfs_opt_enable_cc,
|
||||
#endif
|
||||
#ifdef CONFIG_SDP
|
||||
ecryptfs_opt_userid, ecryptfs_opt_sdp, ecryptfs_opt_chamber_dirs, ecryptfs_opt_partition_id,
|
||||
#endif
|
||||
ecryptfs_opt_base, ecryptfs_opt_type, ecryptfs_opt_label,
|
||||
ecryptfs_opt_err };
|
||||
|
@ -224,12 +211,6 @@ static const match_table_t tokens = {
|
|||
#endif
|
||||
#if defined(CONFIG_CRYPTO_FIPS) && !defined(CONFIG_FORCE_DISABLE_FIPS)
|
||||
{ecryptfs_opt_enable_cc, "ecryptfs_enable_cc"},
|
||||
#endif
|
||||
#ifdef CONFIG_SDP
|
||||
{ecryptfs_opt_chamber_dirs, "chamber=%s"},
|
||||
{ecryptfs_opt_userid, "userid=%s"},
|
||||
{ecryptfs_opt_sdp, "sdp_enabled"},
|
||||
{ecryptfs_opt_partition_id, "partition_id=%u"},
|
||||
#endif
|
||||
{ecryptfs_opt_base, "base=%s"},
|
||||
{ecryptfs_opt_type, "type=%s"},
|
||||
|
@ -273,13 +254,6 @@ static void ecryptfs_init_mount_crypt_stat(
|
|||
INIT_LIST_HEAD(&mount_crypt_stat->global_auth_tok_list);
|
||||
mutex_init(&mount_crypt_stat->global_auth_tok_list_mutex);
|
||||
mount_crypt_stat->flags |= ECRYPTFS_MOUNT_CRYPT_STAT_INITIALIZED;
|
||||
|
||||
#ifdef CONFIG_SDP
|
||||
spin_lock_init(&mount_crypt_stat->chamber_dir_list_lock);
|
||||
INIT_LIST_HEAD(&mount_crypt_stat->chamber_dir_list);
|
||||
|
||||
mount_crypt_stat->partition_id = -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void ecryptfs_init_propagate_stat(
|
||||
|
@ -525,78 +499,6 @@ static int ecryptfs_parse_options(struct ecryptfs_sb_info *sbi, char *options,
|
|||
strncpy(cipher_mode, ECRYPTFS_AES_CBC_MODE, ECRYPTFS_MAX_CIPHER_MODE_SIZE);
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_SDP
|
||||
case ecryptfs_opt_userid: {
|
||||
char *userid_src = args[0].from;
|
||||
int userid =
|
||||
(int)simple_strtol(userid_src,
|
||||
&userid_src, 0);
|
||||
sbi->userid = userid;
|
||||
mount_crypt_stat->userid = userid;
|
||||
/*
|
||||
* Enabling SDP by default for Knox container.
|
||||
*/
|
||||
mount_crypt_stat->flags |= ECRYPTFS_MOUNT_SDP_ENABLED;
|
||||
}
|
||||
break;
|
||||
case ecryptfs_opt_sdp:
|
||||
mount_crypt_stat->flags |= ECRYPTFS_MOUNT_SDP_ENABLED;
|
||||
break;
|
||||
case ecryptfs_opt_chamber_dirs: {
|
||||
char *chamber_dirs = args[0].from;
|
||||
char *token = NULL;
|
||||
|
||||
/**
|
||||
* chamber directories by mount-option.
|
||||
* The userid in the mount option is used as engine_id
|
||||
*
|
||||
* TODO : This won't work when chamber_dirs mount option comes before
|
||||
* user_id option.
|
||||
*/
|
||||
printk("%s : chamber dirs : %s\n", __func__, chamber_dirs);
|
||||
while ((token = strsep(&chamber_dirs, "|")) != NULL)
|
||||
if(!is_chamber_directory(mount_crypt_stat, (const unsigned char *)token, NULL))
|
||||
add_chamber_directory(mount_crypt_stat,
|
||||
mount_crypt_stat->userid, (const unsigned char *)token);
|
||||
}
|
||||
break;
|
||||
case ecryptfs_opt_partition_id: {
|
||||
char *partition_id_str = args[0].from;
|
||||
mount_crypt_stat->partition_id =
|
||||
(int)simple_strtol(partition_id_str,
|
||||
&partition_id_str, 0);
|
||||
printk("%s : partition_id : %d", __func__, mount_crypt_stat->partition_id);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case ecryptfs_opt_base:
|
||||
base_path_src = args[0].from;
|
||||
base_path_dst = propagate_stat->base_path;
|
||||
strncpy(base_path_dst, base_path_src, ECRYPTFS_BASE_PATH_SIZE);
|
||||
break;
|
||||
case ecryptfs_opt_type:
|
||||
propagate_type = match_strdup(&args[0]);
|
||||
if (!propagate_type)
|
||||
return -ENOMEM;
|
||||
if (!strncmp(propagate_type, "default", strlen("default")))
|
||||
propagate_stat->propagate_type = TYPE_E_DEFAULT;
|
||||
else if (!strncmp(propagate_type, "read", strlen("read")))
|
||||
propagate_stat->propagate_type = TYPE_E_READ;
|
||||
else if (!strncmp(propagate_type, "write", strlen("write")))
|
||||
propagate_stat->propagate_type = TYPE_E_WRITE;
|
||||
else {
|
||||
printk(KERN_WARNING
|
||||
"%s: eCryptfs: unrecognized option [type=%s]\n",
|
||||
__func__, propagate_type);
|
||||
propagate_stat->propagate_type = TYPE_E_NONE;
|
||||
}
|
||||
kfree(propagate_type);
|
||||
break;
|
||||
case ecryptfs_opt_label:
|
||||
label_src = args[0].from;
|
||||
label_dst = propagate_stat->label;
|
||||
strncpy(label_dst, label_src, ECRYPTFS_LABEL_SIZE);
|
||||
break;
|
||||
case ecryptfs_opt_err:
|
||||
default:
|
||||
printk(KERN_WARNING
|
||||
|
@ -759,10 +661,6 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags
|
|||
goto out;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SDP
|
||||
sbi->userid = -1;
|
||||
#endif
|
||||
|
||||
rc = ecryptfs_parse_options(sbi, raw_data, &check_ruid);
|
||||
if (rc) {
|
||||
err = "Error parsing options";
|
||||
|
|
|
@ -28,8 +28,6 @@
|
|||
#include <linux/pagemap.h>
|
||||
|
||||
#include "ecryptfs_kernel.h"
|
||||
#include "ecryptfs_dek.h"
|
||||
|
||||
|
||||
extern spinlock_t inode_sb_list_lock;
|
||||
static int ecryptfs_mm_debug = 0;
|
||||
|
|
|
@ -33,9 +33,6 @@
|
|||
#include <linux/statfs.h>
|
||||
#include <linux/magic.h>
|
||||
#include "ecryptfs_kernel.h"
|
||||
#ifdef CONFIG_SDP
|
||||
#include "ecryptfs_dek.h"
|
||||
#endif
|
||||
|
||||
struct kmem_cache *ecryptfs_inode_info_cache;
|
||||
|
||||
|
@ -63,10 +60,6 @@ static struct inode *ecryptfs_alloc_inode(struct super_block *sb)
|
|||
mutex_init(&inode_info->lower_file_mutex);
|
||||
atomic_set(&inode_info->lower_file_count, 0);
|
||||
inode_info->lower_file = NULL;
|
||||
#ifdef CONFIG_SDP
|
||||
// get userid from super block
|
||||
inode_info->crypt_stat.engine_id = -1;
|
||||
#endif
|
||||
inode = &inode_info->vfs_inode;
|
||||
out:
|
||||
return inode;
|
||||
|
@ -170,16 +163,6 @@ static int ecryptfs_show_options(struct seq_file *m, struct dentry *root)
|
|||
}
|
||||
mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex);
|
||||
|
||||
#ifdef CONFIG_SDP
|
||||
seq_printf(m, ",userid=%d", mount_crypt_stat->userid);
|
||||
|
||||
if (mount_crypt_stat->flags & ECRYPTFS_MOUNT_SDP_ENABLED){
|
||||
seq_printf(m, ",sdp_enabled");
|
||||
}
|
||||
if (mount_crypt_stat->partition_id >= 0){
|
||||
seq_printf(m, ",partition_id=%d", mount_crypt_stat->partition_id);
|
||||
}
|
||||
#endif
|
||||
seq_printf(m, ",ecryptfs_cipher=%s",
|
||||
mount_crypt_stat->global_default_cipher_name);
|
||||
|
||||
|
|
|
@ -168,9 +168,6 @@ int inode_init_always(struct super_block *sb, struct inode *inode)
|
|||
mapping->assoc_mapping = NULL;
|
||||
mapping->backing_dev_info = &default_backing_dev_info;
|
||||
mapping->writeback_index = 0;
|
||||
#ifdef CONFIG_SDP
|
||||
mapping->userid = 0;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If the block_device provides a backing_dev_info for client
|
||||
|
|
|
@ -51,9 +51,6 @@ void get_derived_permission(struct dentry *parent, struct dentry *dentry)
|
|||
struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
|
||||
struct sdcardfs_inode_info *info = SDCARDFS_I(dentry->d_inode);
|
||||
struct sdcardfs_inode_info *parent_info= SDCARDFS_I(parent->d_inode);
|
||||
#ifdef CONFIG_SDP
|
||||
struct sdcardfs_dentry_info *parent_dinfo = SDCARDFS_D(parent);
|
||||
#endif
|
||||
appid_t appid;
|
||||
|
||||
/* By default, each inode inherits from its parent.
|
||||
|
@ -157,19 +154,6 @@ void get_derived_permission(struct dentry *parent, struct dentry *dentry)
|
|||
case PERM_ANDROID_KNOX_PACKAGE_DATA:
|
||||
break;
|
||||
}
|
||||
#ifdef CONFIG_SDP
|
||||
if((parent_info->perm == PERM_PRE_ROOT) && (parent_dinfo->under_knox) && (parent_dinfo->userid >= 0)) {
|
||||
info->userid = parent_dinfo->userid;
|
||||
}
|
||||
|
||||
if(parent_dinfo->under_knox) {
|
||||
if(parent_dinfo->permission == PERMISSION_UNDER_ANDROID) {
|
||||
if (parent_dinfo->appid != 0){
|
||||
info->d_uid = multiuser_get_uid(parent_info->userid, parent_dinfo->appid);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* set vfs_inode from sdcardfs_inode */
|
||||
|
|
|
@ -209,16 +209,12 @@ struct sdcardfs_dentry_info {
|
|||
spinlock_t lock; /* protects lower_path */
|
||||
struct path lower_path;
|
||||
struct path orig_path;
|
||||
#ifdef CONFIG_SDP
|
||||
int under_knox;
|
||||
int userid;
|
||||
#define PERMISSION_PRE_ROOT 0
|
||||
#define PERMISSION_ROOT 1
|
||||
#define PERMISSION_ANDROID 2
|
||||
#define PERMISSION_UNDER_ANDROID 3
|
||||
int permission;
|
||||
appid_t appid;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct sdcardfs_mount_options {
|
||||
|
|
|
@ -669,9 +669,6 @@ struct address_space {
|
|||
spinlock_t private_lock; /* for use by the address_space */
|
||||
struct list_head private_list; /* ditto */
|
||||
struct address_space *assoc_mapping; /* ditto */
|
||||
#ifdef CONFIG_SDP
|
||||
int userid;
|
||||
#endif
|
||||
} __attribute__((aligned(sizeof(long))));
|
||||
/*
|
||||
* On most architectures that alignment is already the case; but
|
||||
|
|
|
@ -24,9 +24,6 @@ enum mapping_flags {
|
|||
AS_ENOSPC = __GFP_BITS_SHIFT + 1, /* ENOSPC on async write */
|
||||
AS_MM_ALL_LOCKS = __GFP_BITS_SHIFT + 2, /* under mm_take_all_locks() */
|
||||
AS_UNEVICTABLE = __GFP_BITS_SHIFT + 3, /* e.g., ramdisk, SHM_LOCK */
|
||||
#ifdef CONFIG_SDP
|
||||
AS_SENSITIVE = __GFP_BITS_SHIFT + 5, /* Group of sensitive pages to be cleaned up */
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline void mapping_set_error(struct address_space *mapping, int error)
|
||||
|
@ -71,25 +68,6 @@ static inline void mapping_set_gfp_mask(struct address_space *m, gfp_t mask)
|
|||
(__force unsigned long)mask;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SDP
|
||||
static inline void mapping_set_sensitive(struct address_space *mapping)
|
||||
{
|
||||
set_bit(AS_SENSITIVE, &mapping->flags);
|
||||
}
|
||||
|
||||
static inline void mapping_clear_sensitive(struct address_space *mapping)
|
||||
{
|
||||
clear_bit(AS_SENSITIVE, &mapping->flags);
|
||||
}
|
||||
|
||||
static inline int mapping_sensitive(struct address_space *mapping)
|
||||
{
|
||||
if (mapping)
|
||||
return test_bit(AS_SENSITIVE, &mapping->flags);
|
||||
return !!mapping;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The page cache can done in larger chunks than
|
||||
* one page, because it allows for more efficient
|
||||
|
|
|
@ -1629,9 +1629,6 @@ struct task_struct {
|
|||
#ifdef CONFIG_HAVE_HW_BREAKPOINT
|
||||
atomic_t ptrace_bp_refcnt;
|
||||
#endif
|
||||
#ifdef CONFIG_SDP
|
||||
unsigned int sensitive;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Future-safe accessor for struct task_struct's cpus_allowed. */
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Sensitive Data Protection
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef PAGEMAP_H_
|
||||
#define PAGEMAP_H_
|
||||
|
||||
#include <sdp/common.h>
|
||||
#include <linux/pagemap.h>
|
||||
|
||||
void sdp_page_cleanup(struct page *page);
|
||||
|
||||
#endif /* PAGEMAP_H_ */
|
|
@ -1,33 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Sensitive Data Protection
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef SDP_COMMON_H__
|
||||
#define SDP_COMMON_H__
|
||||
|
||||
#define PER_USER_RANGE 100000
|
||||
|
||||
#define KNOX_PERSONA_BASE_ID 100
|
||||
#define DEK_USER_ID_OFFSET 100
|
||||
|
||||
#define BASE_ID KNOX_PERSONA_BASE_ID
|
||||
#define GET_ARR_IDX(__userid) (__userid - BASE_ID)
|
||||
|
||||
#define SDP_CACHE_CLEANUP_DEBUG 0
|
||||
|
||||
#endif
|
|
@ -1,32 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Sensitive Data Protection
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_DEK_AES_H
|
||||
#define _LINUX_DEK_AES_H
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <sdp/dek_aes.h>
|
||||
|
||||
int dek_aes_encrypt(kek_t *kek, char *src, char *dst, int len);
|
||||
int dek_aes_decrypt(kek_t *kek, char *src, char *dst, int len);
|
||||
|
||||
#endif
|
|
@ -1,132 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Sensitive Data Protection
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef DEK_COMMON_H__
|
||||
#define DEK_COMMON_H__
|
||||
|
||||
// ==== kernel configs
|
||||
#include <linux/limits.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
#include <sdp/common.h>
|
||||
|
||||
// ==== common configs
|
||||
#define SDPK_DEFAULT_ALGOTYPE (SDPK_ALGOTYPE_ASYMM_ECDH)
|
||||
#define SDPK_ALGOTYPE_ASYMM_RSA 0
|
||||
#define SDPK_ALGOTYPE_ASYMM_DH 1
|
||||
#define SDPK_ALGOTYPE_ASYMM_ECDH 2
|
||||
|
||||
//#define DEK_ENGINE_LOCAL_KEK
|
||||
#define KEK_RSA_KEY_BITS 2048
|
||||
#define KEK_MK_BITS 256
|
||||
#define KEK_SS_BITS 256
|
||||
|
||||
#define DH_DEFAULT_GENERATOR DH_GENERATOR_2
|
||||
#define DH_MAXLEN 256
|
||||
|
||||
#define DEK_NAME_LEN 256
|
||||
#define DEK_LEN 32
|
||||
#define DEK_MAXLEN 400 // TODO : need to optimize the length of EDEK DEK_RSA_KEY_BITS/8 : 256 bytes , DH2236 : 280 bytes
|
||||
#define DEK_PW_LEN 32
|
||||
#define KEK_MAXLEN (KEK_RSA_KEY_BITS/4+4)
|
||||
#define KEK_MK_LEN (KEK_MK_BITS/8)
|
||||
#define KEK_SS_LEN (KEK_SS_BITS/8)
|
||||
#define DEK_AES_HEADER 44
|
||||
#define FEK_MAXLEN 32
|
||||
#define EFEK_MAXLEN (FEK_MAXLEN+16)
|
||||
|
||||
#define AES_BLOCK_SIZE 16
|
||||
|
||||
// DEK types
|
||||
#define DEK_TYPE_PLAIN 0
|
||||
#define DEK_TYPE_RSA_ENC 1
|
||||
#define DEK_TYPE_AES_ENC 2
|
||||
//#define DEK_TYPE_DH_PUB 4
|
||||
#define DEK_TYPE_DH_ENC 5
|
||||
#define DEK_TYPE_ECDH256_ENC 6
|
||||
|
||||
// KEK types
|
||||
#define KEK_TYPE_SYM 10
|
||||
#define KEK_TYPE_RSA_PUB 11
|
||||
#define KEK_TYPE_RSA_PRIV 12
|
||||
#define KEK_TYPE_DH_PUB 13
|
||||
#define KEK_TYPE_DH_PRIV 14
|
||||
#define KEK_TYPE_ECDH256_PUB 15
|
||||
#define KEK_TYPE_ECDH256_PRIV 16
|
||||
|
||||
#define SDPK_PATH_MAX 256
|
||||
#define SDPK_PATH_FMT "/data/system/users/%d/SDPK_%s"
|
||||
#define SDPK_RPRI_NAME "Rpri"
|
||||
#define SDPK_RPUB_NAME "Rpub"
|
||||
#define SDPK_DPRI_NAME "Dpri"
|
||||
#define SDPK_DPUB_NAME "Dpub"
|
||||
#define SDPK_EDPRI_NAME "EDpri"
|
||||
#define SDPK_EDPUB_NAME "EDpub"
|
||||
#define SDPK_SYM_NAME "sym"
|
||||
|
||||
typedef struct _password{
|
||||
unsigned int len;
|
||||
unsigned char buf[DEK_MAXLEN];
|
||||
}password_t;
|
||||
|
||||
typedef struct _key{
|
||||
unsigned int type;
|
||||
unsigned int len;
|
||||
unsigned char buf[DEK_MAXLEN];
|
||||
}dek_t;
|
||||
|
||||
typedef struct _kek{
|
||||
unsigned int type;
|
||||
unsigned int len;
|
||||
unsigned char buf[KEK_MAXLEN];
|
||||
}kek_t;
|
||||
|
||||
typedef struct _payload{
|
||||
unsigned int efek_len;
|
||||
unsigned int dpub_len;
|
||||
unsigned char efek_buf[EFEK_MAXLEN];
|
||||
unsigned char dpub_buf[DH_MAXLEN];
|
||||
}dh_payload;
|
||||
|
||||
/* Debug */
|
||||
#define DEK_DEBUG 0
|
||||
|
||||
#if DEK_DEBUG
|
||||
#define DEK_LOGD(...) printk("dek: "__VA_ARGS__)
|
||||
#else
|
||||
#define DEK_LOGD(...)
|
||||
#endif /* DEK_DEBUG */
|
||||
#define DEK_LOGE(...) printk("dek: "__VA_ARGS__)
|
||||
|
||||
void key_dump(unsigned char *buf, int len);
|
||||
|
||||
int is_kek_available(int userid, int kek_type);
|
||||
|
||||
int dek_create_sysfs_asym_alg(struct device *d);
|
||||
int dek_create_sysfs_key_dump(struct device *d);
|
||||
int get_sdp_sysfs_asym_alg(void);
|
||||
int get_sdp_sysfs_key_dump(void);
|
||||
|
||||
int is_root(void);
|
||||
int is_current_epmd(void);
|
||||
int is_current_adbd(void);
|
||||
int is_system_server(void);
|
||||
|
||||
#endif
|
|
@ -1,104 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Sensitive Data Protection
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef DEK_IOCTL_H_
|
||||
#define DEK_IOCTL_H_
|
||||
|
||||
#include <sdp/dek_common.h>
|
||||
#define __DEKIOC 0x77
|
||||
|
||||
typedef struct _dek_arg_generate_dek {
|
||||
int engine_id;
|
||||
dek_t dek;
|
||||
}dek_arg_generate_dek;
|
||||
|
||||
typedef struct _dek_arg_encrypt_dek {
|
||||
int engine_id;
|
||||
dek_t plain_dek;
|
||||
dek_t enc_dek;
|
||||
}dek_arg_encrypt_dek;
|
||||
|
||||
typedef struct _dek_arg_decrypt_dek {
|
||||
int engine_id;
|
||||
dek_t plain_dek;
|
||||
dek_t enc_dek;
|
||||
}dek_arg_decrypt_dek;
|
||||
|
||||
typedef struct _dek_arg_is_kek_avail {
|
||||
int engine_id;
|
||||
int kek_type;
|
||||
int ret;
|
||||
}dek_arg_is_kek_avail;
|
||||
|
||||
/*
|
||||
* DEK_ON_BOOT indicates that there's persona in the system.
|
||||
*
|
||||
* The driver will load public key and encrypted private key.
|
||||
*/
|
||||
typedef struct _dek_arg_on_boot {
|
||||
int engine_id;
|
||||
int user_id;
|
||||
kek_t SDPK_Rpub;
|
||||
kek_t SDPK_Dpub;
|
||||
kek_t SDPK_EDpub;
|
||||
}dek_arg_on_boot;
|
||||
|
||||
typedef struct _dek_arg_on_device_locked {
|
||||
int engine_id;
|
||||
int user_id;
|
||||
}dek_arg_on_device_locked;
|
||||
|
||||
typedef struct _dek_arg_on_device_unlocked {
|
||||
int engine_id;
|
||||
kek_t SDPK_Rpri;
|
||||
kek_t SDPK_Dpri;
|
||||
kek_t SDPK_EDpri;
|
||||
kek_t SDPK_sym;
|
||||
}dek_arg_on_device_unlocked;
|
||||
|
||||
typedef struct _dek_arg_on_user_added {
|
||||
int engine_id;
|
||||
int user_id;
|
||||
kek_t SDPK_Rpub;
|
||||
kek_t SDPK_Dpub;
|
||||
kek_t SDPK_EDpub;
|
||||
}dek_arg_on_user_added;
|
||||
|
||||
typedef struct _dek_arg_on_user_removed {
|
||||
int engine_id;
|
||||
int user_id;
|
||||
}dek_arg_on_user_removed, dek_arg_disk_cache_cleanup;
|
||||
|
||||
// SDP driver events
|
||||
#define DEK_ON_BOOT _IOW(__DEKIOC, 0, unsigned int)
|
||||
#define DEK_ON_DEVICE_LOCKED _IOW(__DEKIOC, 4, unsigned int)
|
||||
#define DEK_ON_DEVICE_UNLOCKED _IOW(__DEKIOC, 5, unsigned int)
|
||||
#define DEK_ON_USER_ADDED _IOW(__DEKIOC, 6, unsigned int)
|
||||
#define DEK_ON_USER_REMOVED _IOW(__DEKIOC, 7, unsigned int)
|
||||
#define DEK_ON_CHANGE_PASSWORD _IOW(__DEKIOC, 8, unsigned int) // @Deprecated
|
||||
|
||||
// SDP driver DEK requests
|
||||
#define DEK_GENERATE_DEK _IOW(__DEKIOC, 1, unsigned int)
|
||||
#define DEK_ENCRYPT_DEK _IOW(__DEKIOC, 2, unsigned int)
|
||||
#define DEK_DECRYPT_DEK _IOR(__DEKIOC, 3, unsigned int)
|
||||
#define DEK_GET_KEK _IOW(__DEKIOC, 9, unsigned int)
|
||||
#define DEK_DISK_CACHE_CLEANUP _IOW(__DEKIOC, 10, unsigned int)
|
||||
#define DEK_IS_KEK_AVAIL _IOW(__DEKIOC, 11, unsigned int)
|
||||
|
||||
#endif /* DEK_IOCTL_H_ */
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Sensitive Data Protection
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef DLP_IOCTL_H_
|
||||
#define DLP_IOCTL_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/ioctl.h>
|
||||
|
||||
#define DLP_DEV_PATH "/dev/sdp_dlp"
|
||||
|
||||
#define __DLPIOC 0x78
|
||||
#define MAX_EXT_LENGTH 1000
|
||||
|
||||
typedef struct _dlp_lock_set {
|
||||
int user_id;
|
||||
} dlp_lock_set;
|
||||
|
||||
typedef struct _dlp_extension_set {
|
||||
int user_id;
|
||||
char extensions[MAX_EXT_LENGTH+1];
|
||||
} dlp_extension_set;
|
||||
|
||||
#define DLP_LOCK_ENABLE _IOW(__DLPIOC, 1, dlp_lock_set)
|
||||
#define DLP_LOCK_DISABLE _IOW(__DLPIOC, 2, dlp_lock_set)
|
||||
#define DLP_EXTENSION_SET _IOW(__DLPIOC, 3, dlp_extension_set)
|
||||
|
||||
#endif /* DLP_IOCTL_H_ */
|
|
@ -1,80 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Sensitive Data Protection
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _SDP_FS_HANDLER_H
|
||||
#define _SDP_FS_HANDLER_H
|
||||
|
||||
#include <sdp/dek_common.h>
|
||||
#include <sdp/fs_request.h>
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/limits.h>
|
||||
|
||||
#define SDP_FS_HANDLER_NETLINK 28
|
||||
#define SDP_FS_HANDLER_PID_SET 3001
|
||||
#define SDP_FS_HANDLER_RESULT 3002
|
||||
|
||||
#define OP_SDP_SET_DIR_SENSITIVE 10
|
||||
#define OP_SDP_SET_DIR_PROTECTED 11
|
||||
|
||||
#define OP_SDP_ERROR 99
|
||||
|
||||
typedef struct result {
|
||||
u32 request_id;
|
||||
u8 opcode;
|
||||
s16 ret;
|
||||
}result_t;
|
||||
|
||||
/** The request state */
|
||||
enum req_state {
|
||||
SDP_FS_HANDLER_REQ_INIT = 0,
|
||||
SDP_FS_HANDLER_REQ_PENDING,
|
||||
SDP_FS_HANDLER_REQ_FINISHED
|
||||
};
|
||||
|
||||
typedef struct __sdp_fs_handler_contorl {
|
||||
struct list_head pending_list;
|
||||
//wait_queue_head_t waitq;
|
||||
spinlock_t lock;
|
||||
|
||||
/** The next unique request id */
|
||||
u32 reqctr;
|
||||
}sdp_fs_handler_control_t;
|
||||
|
||||
typedef struct __sdp_fs_handler_request {
|
||||
u32 id;
|
||||
u8 opcode;
|
||||
|
||||
struct list_head list;
|
||||
/** refcount */
|
||||
atomic_t count;
|
||||
|
||||
enum req_state state;
|
||||
|
||||
sdp_fs_command_t command;
|
||||
result_t result;
|
||||
|
||||
fs_request_cb_t callback;
|
||||
|
||||
/** The request was aborted */
|
||||
u8 aborted;
|
||||
}sdp_fs_handler_request_t;
|
||||
#endif
|
|
@ -1,73 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Sensitive Data Protection
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef FS_REQUEST_H_
|
||||
#define FS_REQUEST_H_
|
||||
|
||||
#include <linux/slab.h>
|
||||
|
||||
#define FSOP_SDP_SET_SENSITIVE 10
|
||||
#define FSOP_SDP_SET_PROTECTED 11
|
||||
|
||||
#define FSOP_DLP_FILE_OPENED 21
|
||||
#define FSOP_DLP_FILE_CLOSED 22
|
||||
#define FSOP_DLP_FILE_INIT 23
|
||||
#define FSOP_DLP_FILE_INIT_RESTRICTED 24
|
||||
#define FSOP_DLP_FILE_REMOVE 25
|
||||
#define FSOP_DLP_FILE_RENAME 26
|
||||
|
||||
#define FSOP_AUDIT_FAIL_ENCRYPT 51
|
||||
#define FSOP_AUDIT_FAIL_DECRYPT 52
|
||||
|
||||
// opcode, ret, inode
|
||||
typedef void (*fs_request_cb_t)(int, int, unsigned long);
|
||||
|
||||
typedef struct sdp_fs_command {
|
||||
int req_id;
|
||||
|
||||
int opcode;
|
||||
int user_id;
|
||||
int part_id;
|
||||
unsigned long ino;
|
||||
int pid;
|
||||
}sdp_fs_command_t;
|
||||
|
||||
extern int sdp_fs_request(sdp_fs_command_t *sdp_req, fs_request_cb_t callback);
|
||||
|
||||
static inline sdp_fs_command_t *sdp_fs_command_alloc(int opcode, int pid,
|
||||
int userid, int partid, unsigned long ino, gfp_t gfp) {
|
||||
sdp_fs_command_t *cmd;
|
||||
|
||||
cmd = kmalloc(sizeof(sdp_fs_command_t), gfp);
|
||||
|
||||
cmd->opcode = opcode;
|
||||
cmd->pid = pid;
|
||||
cmd->user_id = userid;
|
||||
cmd->part_id = partid;
|
||||
cmd->ino = ino;
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
static inline void sdp_fs_command_free(sdp_fs_command_t *cmd)
|
||||
{
|
||||
kzfree(cmd);
|
||||
}
|
||||
|
||||
#endif /* FS_REQUEST_H_ */
|
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Sensitive Data Protection
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _SDP_KEK_PACK_H_
|
||||
#define _SDP_KEK_PACK_H_
|
||||
|
||||
#include <sdp/dek_common.h>
|
||||
|
||||
void init_kek_pack(void);
|
||||
|
||||
int add_kek_pack(int engine_id, int userid);
|
||||
void del_kek_pack(int engine_id);
|
||||
|
||||
int add_kek(int engine_id, kek_t *kek);
|
||||
int del_kek(int engine_id, int kek_type);
|
||||
kek_t *get_kek(int engine_id, int kek_type, int *rc);
|
||||
|
||||
void put_kek(kek_t *kek);
|
||||
|
||||
int is_kek_pack(int engine_id);
|
||||
int is_kek(int engine_id, int kek_type);
|
||||
|
||||
#endif /* _SDP_KEK_PACK_H_ */
|
|
@ -1,94 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Sensitive Data Protection
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _FIPS_CRYPTO_H
|
||||
#define _FIPS_CRYPTO_H
|
||||
|
||||
#include <sdp/dek_common.h>
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#define OP_RSA_ENC 10
|
||||
#define OP_RSA_DEC 11
|
||||
#define OP_DH_DEC 12
|
||||
#define OP_DH_ENC 13
|
||||
#define OP_ECDH_DEC 14
|
||||
#define OP_ECDH_ENC 15
|
||||
|
||||
#define PUB_CRYPTO_ERROR 99
|
||||
|
||||
typedef struct __cipher_param {
|
||||
u32 request_id;
|
||||
u8 opcode;
|
||||
dek_t in;
|
||||
kek_t key;
|
||||
}cipher_param_t;
|
||||
|
||||
typedef struct result {
|
||||
u32 request_id;
|
||||
u8 opcode;
|
||||
s16 ret;
|
||||
dek_t dek;
|
||||
}result_t;
|
||||
|
||||
/** The request state */
|
||||
enum req_state {
|
||||
PUB_CRYPTO_REQ_INIT = 0,
|
||||
PUB_CRYPTO_REQ_PENDING,
|
||||
PUB_CRYPTO_REQ_FINISHED
|
||||
};
|
||||
|
||||
typedef struct pub_crypto_contorl {
|
||||
struct list_head pending_list;
|
||||
//wait_queue_head_t waitq;
|
||||
spinlock_t lock;
|
||||
|
||||
/** The next unique request id */
|
||||
u32 reqctr;
|
||||
}pub_crypto_control_t;
|
||||
|
||||
typedef struct pub_crypto_request {
|
||||
u32 id;
|
||||
u8 opcode;
|
||||
|
||||
struct list_head list;
|
||||
/** refcount */
|
||||
atomic_t count;
|
||||
|
||||
wait_queue_head_t waitq;
|
||||
|
||||
enum req_state state;
|
||||
|
||||
cipher_param_t cipher_param;
|
||||
|
||||
result_t result;
|
||||
|
||||
/** The request was aborted */
|
||||
u8 aborted;
|
||||
}pub_crypto_request_t;
|
||||
|
||||
int rsa_encryptByPub(dek_t *dek, dek_t *edek, kek_t *key);
|
||||
int rsa_decryptByPair(dek_t *edek, dek_t *dek, kek_t *key);
|
||||
int dh_decryptEDEK(dek_t *edek, dek_t *dek, kek_t *key);
|
||||
int dh_encryptDEK(dek_t *dek, dek_t *edek, kek_t *key);
|
||||
int ecdh_decryptEDEK(dek_t *edek, dek_t *dek, kek_t *key);
|
||||
int ecdh_encryptDEK(dek_t *dek, dek_t *edek, kek_t *key);
|
||||
#endif
|
|
@ -1,55 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Sensitive Data Protection
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _UAPI_SDP_MM_H_
|
||||
#define _UAPI_SDP_MM_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/ioctl.h>
|
||||
|
||||
#define MAX_SENSITIVE_PROC 100
|
||||
|
||||
/*
|
||||
* struct sdp_mm_sensitive_proc_req - for setting the process as sensitive
|
||||
* @proc_id - process id of the process to be set (as sensitive)
|
||||
*/
|
||||
struct sdp_mm_sensitive_proc_req {
|
||||
unsigned int proc_id; /* in */
|
||||
};
|
||||
|
||||
/*
|
||||
* struct sdp_mm_sensitive_proc_list_resp - for querying sensitive process list
|
||||
* @sensitive_proc_list_len - number of sensitive processes in the list
|
||||
* @sensitive_proc_list - sensitive process list
|
||||
*/
|
||||
struct sdp_mm_sensitive_proc_list_resp {
|
||||
unsigned int sensitive_proc_list_len;
|
||||
unsigned int sensitive_proc_list[MAX_SENSITIVE_PROC];
|
||||
};
|
||||
|
||||
|
||||
#define SDP_MM_IOC_MAGIC 0x77
|
||||
|
||||
#define SDP_MM_IOCTL_PROC_SENSITIVE_QUERY_REQ \
|
||||
_IOWR(SDP_MM_IOC_MAGIC, 1, struct sdp_mm_sensitive_proc_list_resp)
|
||||
|
||||
#define SDP_MM_IOCTL_SET_SENSITIVE_PROC_REQ \
|
||||
_IOWR(SDP_MM_IOC_MAGIC, 2, struct sdp_mm_sensitive_proc_req)
|
||||
|
||||
#endif /* _UAPI_SDP_MM_H_ */
|
|
@ -507,10 +507,6 @@ config MIN_DIRTY_THRESH_PAGES
|
|||
disables this option.)
|
||||
Do not use it if you unsure.
|
||||
|
||||
config SDP_CACHE_CLEANUP
|
||||
bool "SDP requirement. cache cleanup"
|
||||
depends on SDP
|
||||
default n
|
||||
|
||||
config MMAP_READAROUND_LIMIT
|
||||
int "Limit mmap readaround upperbound"
|
||||
|
@ -518,4 +514,4 @@ config MMAP_READAROUND_LIMIT
|
|||
help
|
||||
Inappropriate mmap readaround size can hurt device performance
|
||||
during the sluggish situation. Add the hard upper-limit for
|
||||
mmap readaround.
|
||||
mmap readaround.
|
|
@ -36,10 +36,6 @@
|
|||
#include <linux/cleancache.h>
|
||||
#include "internal.h"
|
||||
|
||||
#ifdef CONFIG_SDP
|
||||
#include <sdp/cache_cleanup.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* FIXME: remove all knowledge of the buffer layer from the core VM
|
||||
*/
|
||||
|
@ -118,11 +114,6 @@ void __delete_from_page_cache(struct page *page)
|
|||
{
|
||||
struct address_space *mapping = page->mapping;
|
||||
|
||||
#ifdef CONFIG_SDP
|
||||
if(mapping_sensitive(mapping))
|
||||
sdp_page_cleanup(page);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* if we're uptodate, flush out into the cleancache, otherwise
|
||||
* invalidate any existing cleancache entries. We can't leave
|
||||
|
|
|
@ -33,7 +33,3 @@ obj-$(CONFIG_TIMA_UEVENT) += tima_uevent/
|
|||
|
||||
#TZ ICCC
|
||||
obj-$(CONFIG_TZ_ICCC) += tz_iccc/
|
||||
|
||||
# Knox SDP
|
||||
obj-$(CONFIG_SDP) += sdp/
|
||||
obj-$(CONFIG_SDP) += sdp/built-in.o
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
#
|
||||
# Makefile for DEK and DLP modules
|
||||
#
|
||||
|
||||
obj-$(CONFIG_SDP) += dek.o dek_aes.o sdp_mm.o pub_crypto_emul.o dek_sysfs.o cache_cleanup.o kek_pack.o fs_handler.o
|
||||
obj-$(CONFIG_DLP) += sdp_dlp.o
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Sensitive Data Protection
|
||||
*
|
||||
* 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 <sdp/common.h>
|
||||
#include <sdp/cache_cleanup.h>
|
||||
|
||||
#if SDP_CACHE_CLEANUP_DEBUG
|
||||
static void sdp_page_dump(unsigned char *buf, int len, const char* str)
|
||||
{
|
||||
unsigned int i;
|
||||
char s[512];
|
||||
|
||||
s[0] = 0;
|
||||
for(i=0;i<len && i<32;++i) {
|
||||
char tmp[8];
|
||||
sprintf(tmp, " %02x", buf[i]);
|
||||
strcat(s, tmp);
|
||||
}
|
||||
|
||||
if (len > 32) {
|
||||
char tmp[8];
|
||||
sprintf(tmp, " ...");
|
||||
strcat(s, tmp);
|
||||
}
|
||||
|
||||
printk("%s [%s len=%d]\n", s, str, len);
|
||||
}
|
||||
#else
|
||||
static void sdp_page_dump(unsigned char *buf, int len, const char* str) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
void sdp_page_cleanup(struct page *page)
|
||||
{
|
||||
if(page && page->mapping) {
|
||||
if(mapping_sensitive(page->mapping)) {
|
||||
void *d;
|
||||
|
||||
#if SDP_CACHE_CLEANUP_DEBUG
|
||||
printk("%s : deleting [%s] sensitive page.\n",
|
||||
__func__, page->mapping->host->i_sb->s_type->name);
|
||||
//dump_stack();
|
||||
#endif
|
||||
d = kmap_atomic(page);
|
||||
if(d) {
|
||||
sdp_page_dump((unsigned char *)d, PAGE_SIZE, "freeing");
|
||||
clear_page(d);
|
||||
sdp_page_dump((unsigned char *)d, PAGE_SIZE, "freed");
|
||||
kunmap_atomic(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
1185
security/sdp/dek.c
1185
security/sdp/dek.c
File diff suppressed because it is too large
Load diff
|
@ -1,107 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Sensitive Data Protection
|
||||
*
|
||||
* 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 <linux/err.h>
|
||||
#include <sdp/dek_common.h>
|
||||
#include <sdp/dek_aes.h>
|
||||
|
||||
static struct crypto_blkcipher *dek_aes_key_setup(kek_t *kek)
|
||||
{
|
||||
struct crypto_blkcipher *tfm = NULL;
|
||||
|
||||
tfm = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC);
|
||||
if (!IS_ERR(tfm)) {
|
||||
crypto_blkcipher_setkey(tfm, kek->buf, kek->len);
|
||||
} else {
|
||||
printk("dek: failed to alloc blkcipher\n");
|
||||
}
|
||||
return tfm;
|
||||
}
|
||||
|
||||
|
||||
static void dek_aes_key_free(struct crypto_blkcipher *tfm)
|
||||
{
|
||||
crypto_free_blkcipher(tfm);
|
||||
}
|
||||
|
||||
static int __dek_aes_encrypt(struct crypto_blkcipher *tfm, char *src, char *dst, int len) {
|
||||
struct blkcipher_desc desc;
|
||||
struct scatterlist src_sg, dst_sg;
|
||||
int bsize = crypto_blkcipher_ivsize(tfm);
|
||||
u8 iv[bsize];
|
||||
|
||||
memset(&iv, 0, sizeof(iv));
|
||||
desc.tfm = tfm;
|
||||
desc.info = iv;
|
||||
desc.flags = 0;
|
||||
|
||||
sg_init_one(&src_sg, src, len);
|
||||
sg_init_one(&dst_sg, dst, len);
|
||||
|
||||
return crypto_blkcipher_encrypt_iv(&desc, &dst_sg, &src_sg, len);
|
||||
}
|
||||
|
||||
static int __dek_aes_decrypt(struct crypto_blkcipher *tfm, char *src, char *dst, int len) {
|
||||
struct blkcipher_desc desc;
|
||||
struct scatterlist src_sg, dst_sg;
|
||||
int bsize = crypto_blkcipher_ivsize(tfm);
|
||||
u8 iv[bsize];
|
||||
|
||||
memset(&iv, 0, sizeof(iv));
|
||||
desc.tfm = tfm;
|
||||
desc.info = iv;
|
||||
desc.flags = 0;
|
||||
|
||||
sg_init_one(&src_sg, src, len);
|
||||
sg_init_one(&dst_sg, dst, len);
|
||||
|
||||
return crypto_blkcipher_decrypt_iv(&desc, &dst_sg, &src_sg, len);
|
||||
}
|
||||
|
||||
int dek_aes_encrypt(kek_t *kek, char *src, char *dst, int len) {
|
||||
int rc;
|
||||
struct crypto_blkcipher *tfm;
|
||||
|
||||
if(kek == NULL) return -EINVAL;
|
||||
|
||||
tfm = dek_aes_key_setup(kek);
|
||||
|
||||
if(tfm) {
|
||||
rc = __dek_aes_encrypt(tfm, src, dst, len);
|
||||
dek_aes_key_free(tfm);
|
||||
return rc;
|
||||
} else
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
int dek_aes_decrypt(kek_t *kek, char *src, char *dst, int len) {
|
||||
int rc;
|
||||
struct crypto_blkcipher *tfm;
|
||||
|
||||
if(kek == NULL) return -EINVAL;
|
||||
|
||||
tfm = dek_aes_key_setup(kek);
|
||||
|
||||
if(tfm) {
|
||||
rc = __dek_aes_decrypt(tfm, src, dst, len);
|
||||
dek_aes_key_free(tfm);
|
||||
return rc;
|
||||
} else
|
||||
return -ENOMEM;
|
||||
}
|
|
@ -1,129 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Sensitive Data Protection
|
||||
*
|
||||
* 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 <linux/kernel.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#include <sdp/dek_common.h>
|
||||
|
||||
static int g_asym_alg = SDPK_DEFAULT_ALGOTYPE;
|
||||
|
||||
#define ALG_NAME_RSA_NAME "RSA"
|
||||
#define ALG_NAME_DH_NAME "DH"
|
||||
#define ALG_NAME_ECDH_NAME "ECDH"
|
||||
|
||||
static ssize_t dek_show_asym_alg(struct device *dev,
|
||||
struct device_attribute *attr, char *buf) {
|
||||
|
||||
switch(g_asym_alg) {
|
||||
case SDPK_ALGOTYPE_ASYMM_RSA:
|
||||
return sprintf(buf, "%s\n", ALG_NAME_RSA_NAME);
|
||||
case SDPK_ALGOTYPE_ASYMM_DH:
|
||||
return sprintf(buf, "%s\n", ALG_NAME_DH_NAME);
|
||||
case SDPK_ALGOTYPE_ASYMM_ECDH:
|
||||
return sprintf(buf, "%s\n", ALG_NAME_ECDH_NAME);
|
||||
default:
|
||||
return sprintf(buf, "unknown\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t dek_set_asym_alg(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count) {
|
||||
if(!strncmp(ALG_NAME_RSA_NAME, buf, strlen(ALG_NAME_RSA_NAME))) {
|
||||
g_asym_alg = SDPK_ALGOTYPE_ASYMM_RSA;
|
||||
return strlen(ALG_NAME_RSA_NAME);
|
||||
}
|
||||
|
||||
if(!strncmp(ALG_NAME_DH_NAME, buf, strlen(ALG_NAME_DH_NAME))) {
|
||||
g_asym_alg = SDPK_ALGOTYPE_ASYMM_DH;
|
||||
return strlen(ALG_NAME_DH_NAME);
|
||||
}
|
||||
|
||||
if(!strncmp(ALG_NAME_ECDH_NAME, buf, strlen(ALG_NAME_ECDH_NAME))) {
|
||||
g_asym_alg = SDPK_ALGOTYPE_ASYMM_ECDH;
|
||||
return strlen(ALG_NAME_ECDH_NAME);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(asym_alg, S_IRUSR | S_IWUSR, dek_show_asym_alg, dek_set_asym_alg);
|
||||
|
||||
int dek_create_sysfs_asym_alg(struct device *d) {
|
||||
int error;
|
||||
|
||||
if((error = device_create_file(d, &dev_attr_asym_alg)))
|
||||
return error;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_sdp_sysfs_asym_alg(void) {
|
||||
return g_asym_alg;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SDP_KEY_DUMP
|
||||
static int kek_dump = 0;
|
||||
|
||||
static ssize_t dek_show_key_dump(struct device *dev,
|
||||
struct device_attribute *attr, char *buf) {
|
||||
return sprintf(buf, "%d\n", kek_dump);
|
||||
}
|
||||
|
||||
static ssize_t dek_set_key_dump(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count) {
|
||||
int flag = simple_strtoul(buf, NULL, 10);
|
||||
|
||||
kek_dump = flag;
|
||||
|
||||
return strlen(buf);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(key_dump, S_IRUGO | S_IWUGO, dek_show_key_dump, dek_set_key_dump);
|
||||
|
||||
int dek_create_sysfs_key_dump(struct device *d) {
|
||||
int error;
|
||||
|
||||
if((error = device_create_file(d, &dev_attr_key_dump)))
|
||||
return error;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_sdp_sysfs_key_dump(void) {
|
||||
return kek_dump;
|
||||
}
|
||||
#else
|
||||
int dek_create_sysfs_key_dump(struct device *d) {
|
||||
printk("key_dump feature not available");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_sdp_sysfs_key_dump(void) {
|
||||
printk("key_dump feature not available");
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
|
@ -1,352 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Sensitive Data Protection
|
||||
*
|
||||
* 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 <crypto/internal/hash.h>
|
||||
#include <crypto/scatterwalk.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/wakelock.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/net.h>
|
||||
#include <net/netlink.h>
|
||||
#include <net/sock.h>
|
||||
#include <net/net_namespace.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/audit.h>
|
||||
#include <linux/jiffies.h>
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <sdp/fs_handler.h>
|
||||
#include <sdp/fs_request.h>
|
||||
|
||||
#define RESULT_ARRAY_MAX_LEN 100
|
||||
|
||||
#define CRYPTO_MAX_TIMEOUT HZ/5
|
||||
|
||||
#define SDP_FS_HANDLER_REQ_TIMEOUT 3000
|
||||
|
||||
sdp_fs_handler_control_t g_sdp_fs_handler_control;
|
||||
|
||||
DEFINE_MUTEX(g_send_mutex);
|
||||
static int g_user_pid = 0;
|
||||
static struct sock* g_sock = NULL;
|
||||
|
||||
static int to_netlink_msg(sdp_fs_handler_request_t *req, char **msg);
|
||||
static void request_send(sdp_fs_handler_control_t *con,
|
||||
sdp_fs_handler_request_t *req);
|
||||
static sdp_fs_handler_request_t *request_find(sdp_fs_handler_control_t *con,
|
||||
u32 request_id);
|
||||
static sdp_fs_handler_request_t *request_alloc(u32 opcode);
|
||||
static void request_free(sdp_fs_handler_request_t *req);
|
||||
static void req_dump(sdp_fs_handler_request_t *req, const char *msg);
|
||||
|
||||
/* Debug */
|
||||
#define SDP_FS_HANDLER_DEBUG 0
|
||||
|
||||
#if SDP_FS_HANDLER_DEBUG
|
||||
#define SDP_FS_HANDLER_LOGD(FMT, ...) printk("SDP_FS_HANDLER[%d] : %s " FMT , current->pid, __func__, ##__VA_ARGS__)
|
||||
#else
|
||||
#define SDP_FS_HANDLER_LOGD(FMT, ...)
|
||||
#endif /* SDP_FS_HANDLER_DEBUG */
|
||||
#define SDP_FS_HANDLER_LOGE(FMT, ...) printk("SDP_FS_HANDLER[%d] : %s " FMT , current->pid, __func__, ##__VA_ARGS__)
|
||||
|
||||
static int __handle_request(sdp_fs_handler_request_t *req, char *ret) {
|
||||
int rc = 0;
|
||||
|
||||
struct sk_buff *skb_in = NULL;
|
||||
struct sk_buff *skb_out = NULL;
|
||||
struct nlmsghdr *nlh = NULL;
|
||||
|
||||
char *nl_msg = NULL;
|
||||
int nl_msg_size = 0;
|
||||
|
||||
SDP_FS_HANDLER_LOGD("====================== \t entred\n");
|
||||
|
||||
if(req == NULL) {
|
||||
SDP_FS_HANDLER_LOGE("invalid request\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
request_send(&g_sdp_fs_handler_control, req);
|
||||
|
||||
nl_msg_size = to_netlink_msg(req, &nl_msg);
|
||||
if(nl_msg_size <= 0) {
|
||||
SDP_FS_HANDLER_LOGE("invalid opcode %d\n", req->opcode);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// sending netlink message
|
||||
skb_in = nlmsg_new(nl_msg_size, 0);
|
||||
if (!skb_in) {
|
||||
SDP_FS_HANDLER_LOGE("Failed to allocate new skb: \n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
nlh = nlmsg_put(skb_in, 0, 0, NLMSG_DONE, nl_msg_size, 0);
|
||||
NETLINK_CB(skb_in).dst_group = 0;
|
||||
memcpy(nlmsg_data(nlh), nl_msg, nl_msg_size);
|
||||
|
||||
mutex_lock(&g_send_mutex);
|
||||
rc = nlmsg_unicast(g_sock, skb_in, g_user_pid);
|
||||
mutex_unlock(&g_send_mutex);
|
||||
|
||||
skb_out = skb_dequeue(&g_sock->sk_receive_queue);
|
||||
if(skb_out) {
|
||||
kfree_skb(skb_out);
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int sdp_fs_request(sdp_fs_command_t *cmd, fs_request_cb_t callback){
|
||||
sdp_fs_handler_request_t *req = request_alloc(cmd->opcode);
|
||||
int ret = -1;
|
||||
req_dump(req, "request allocated");
|
||||
|
||||
if(req) {
|
||||
memcpy(&req->command, cmd, sizeof(sdp_fs_command_t));
|
||||
req->command.req_id = req->id;
|
||||
|
||||
req_dump(req, "__handle_reqeust start");
|
||||
ret = __handle_request(req, NULL);
|
||||
req_dump(req, "__handle_reqeust end");
|
||||
|
||||
if(ret != 0) {
|
||||
SDP_FS_HANDLER_LOGE("opcode[%d] failed\n", cmd->opcode);
|
||||
goto error;
|
||||
}
|
||||
} else {
|
||||
SDP_FS_HANDLER_LOGE("request allocation failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
error:
|
||||
request_free(req);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int __recver(struct sk_buff *skb, struct nlmsghdr *nlh)
|
||||
{
|
||||
void *data;
|
||||
u16 msg_type = nlh->nlmsg_type;
|
||||
u32 err = 0;
|
||||
struct audit_status *status_get = NULL;
|
||||
u16 len = 0;
|
||||
|
||||
data = NLMSG_DATA(nlh);
|
||||
len = ntohs(*(uint16_t*) (data+1));
|
||||
switch (msg_type) {
|
||||
case SDP_FS_HANDLER_PID_SET:
|
||||
status_get = (struct audit_status *)data;
|
||||
g_user_pid = status_get->pid;
|
||||
break;
|
||||
case SDP_FS_HANDLER_RESULT:
|
||||
{
|
||||
result_t *result = (result_t *)data;
|
||||
sdp_fs_handler_request_t *req = NULL;
|
||||
|
||||
printk("result : req_id[%d], opcode[%d] ret[%d]\n",
|
||||
result->request_id, result->opcode, result->ret);
|
||||
spin_lock(&g_sdp_fs_handler_control.lock);
|
||||
req = request_find(&g_sdp_fs_handler_control, result->request_id);
|
||||
spin_unlock(&g_sdp_fs_handler_control.lock);
|
||||
|
||||
if(req == NULL) {
|
||||
SDP_FS_HANDLER_LOGE("crypto result :: error! can't find request %d\n",
|
||||
result->request_id);
|
||||
} else {
|
||||
memcpy(&req->result, result, sizeof(result_t));
|
||||
req->state = SDP_FS_HANDLER_REQ_FINISHED;
|
||||
|
||||
if(req->callback)
|
||||
req->callback(req->opcode, req->result.ret, req->command.ino);
|
||||
|
||||
memset(result, 0, sizeof(result_t));
|
||||
request_free(req);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
SDP_FS_HANDLER_LOGE("unknown message type : %d\n", msg_type);
|
||||
break;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Receive messages from netlink socket. */
|
||||
static void recver(struct sk_buff *skb)
|
||||
{
|
||||
struct nlmsghdr *nlh;
|
||||
int len;
|
||||
int err;
|
||||
|
||||
nlh = nlmsg_hdr(skb);
|
||||
len = skb->len;
|
||||
|
||||
err = __recver(skb, nlh);
|
||||
}
|
||||
|
||||
static int to_netlink_msg(sdp_fs_handler_request_t *req, char **msg)
|
||||
{
|
||||
*msg = (char *)&req->command;
|
||||
return sizeof(sdp_fs_command_t);
|
||||
}
|
||||
|
||||
static u32 get_unique_id(sdp_fs_handler_control_t *control)
|
||||
{
|
||||
SDP_FS_HANDLER_LOGD("locked\n");
|
||||
spin_lock(&control->lock);
|
||||
|
||||
control->reqctr++;
|
||||
/* zero is special */
|
||||
if (control->reqctr == 0)
|
||||
control->reqctr = 1;
|
||||
|
||||
spin_unlock(&control->lock);
|
||||
SDP_FS_HANDLER_LOGD("unlocked\n");
|
||||
|
||||
return control->reqctr;
|
||||
}
|
||||
static void req_dump(sdp_fs_handler_request_t *req, const char *msg) {
|
||||
#if SDP_FS_HANDLER_DEBUG
|
||||
SDP_FS_HANDLER_LOGD("DUMP REQUEST [%s] ID[%d] opcode[%d] state[%d]\n", msg, req->id, req->opcode, req->state);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void request_send(sdp_fs_handler_control_t *con,
|
||||
sdp_fs_handler_request_t *req) {
|
||||
spin_lock(&con->lock);
|
||||
SDP_FS_HANDLER_LOGD("entered, control lock\n");
|
||||
|
||||
list_add_tail(&req->list, &con->pending_list);
|
||||
req->state = SDP_FS_HANDLER_REQ_PENDING;
|
||||
|
||||
SDP_FS_HANDLER_LOGD("exit, control unlock\n");
|
||||
spin_unlock(&con->lock);
|
||||
}
|
||||
|
||||
static sdp_fs_handler_request_t *request_find(sdp_fs_handler_control_t *con,
|
||||
u32 request_id) {
|
||||
struct list_head *entry;
|
||||
|
||||
list_for_each(entry, &con->pending_list) {
|
||||
sdp_fs_handler_request_t *req;
|
||||
req = list_entry(entry, sdp_fs_handler_request_t, list);
|
||||
if (req->id == request_id)
|
||||
return req;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct kmem_cache *req_cachep;
|
||||
|
||||
static void request_init(sdp_fs_handler_request_t *req, u32 opcode) {
|
||||
memset(req, 0, sizeof(sdp_fs_handler_request_t));
|
||||
|
||||
req->state = SDP_FS_HANDLER_REQ_INIT;
|
||||
req->id = get_unique_id(&g_sdp_fs_handler_control);
|
||||
|
||||
INIT_LIST_HEAD(&req->list);
|
||||
atomic_set(&req->count, 1);
|
||||
req->aborted = 0;
|
||||
req->opcode = opcode;
|
||||
req->callback = NULL;
|
||||
}
|
||||
|
||||
static sdp_fs_handler_request_t *request_alloc(u32 opcode) {
|
||||
sdp_fs_handler_request_t *req = kmem_cache_alloc(req_cachep, GFP_KERNEL);
|
||||
|
||||
if(req)
|
||||
request_init(req, opcode);
|
||||
return req;
|
||||
}
|
||||
|
||||
static void request_free(sdp_fs_handler_request_t *req)
|
||||
{
|
||||
if(req) {
|
||||
req_dump(req, "request freed");
|
||||
/*
|
||||
* TODO : lock needed here?
|
||||
*/
|
||||
list_del(&req->list);
|
||||
memset(req, 0, sizeof(sdp_fs_handler_request_t));
|
||||
kmem_cache_free(req_cachep, req);
|
||||
} else {
|
||||
SDP_FS_HANDLER_LOGE("req is NULL, skip free\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void control_init(sdp_fs_handler_control_t *con) {
|
||||
SDP_FS_HANDLER_LOGD("sdp_fs_handler_control_init");
|
||||
spin_lock_init(&con->lock);
|
||||
INIT_LIST_HEAD(&con->pending_list);
|
||||
con->reqctr = 0;
|
||||
}
|
||||
|
||||
static int __init sdp_fs_handler_mod_init(void) {
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,4,0))
|
||||
struct netlink_kernel_cfg cfg = {
|
||||
.input = recver,
|
||||
};
|
||||
|
||||
g_sock = netlink_kernel_create(&init_net, SDP_FS_HANDLER_NETLINK, &cfg);
|
||||
#else
|
||||
g_sock = netlink_kernel_create(&init_net, SDP_FS_HANDLER_NETLINK, 0, recver, NULL, THIS_MODULE);
|
||||
#endif
|
||||
|
||||
if (!g_sock) {
|
||||
SDP_FS_HANDLER_LOGE("Failed to create Crypto Netlink Socket .. Exiting \n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
SDP_FS_HANDLER_LOGE("netlink socket is created successfully! \n");
|
||||
|
||||
control_init(&g_sdp_fs_handler_control);
|
||||
req_cachep = kmem_cache_create("sdp_fs_handler_requst",
|
||||
sizeof(sdp_fs_handler_request_t),
|
||||
0, 0, NULL);
|
||||
if (!req_cachep) {
|
||||
netlink_kernel_release(g_sock);
|
||||
SDP_FS_HANDLER_LOGE("Failed to create sdp_fs_handler_requst cache mem.. Exiting \n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit sdp_fs_handler_mod_exit(void) {
|
||||
netlink_kernel_release(g_sock);
|
||||
kmem_cache_destroy(req_cachep);
|
||||
}
|
||||
|
||||
module_init(sdp_fs_handler_mod_init);
|
||||
module_exit(sdp_fs_handler_mod_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("SDP FS netlink");
|
||||
|
|
@ -1,334 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Sensitive Data Protection
|
||||
*
|
||||
* 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 <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
#include <sdp/dek_common.h>
|
||||
|
||||
typedef struct __kek_pack {
|
||||
int engine_id;
|
||||
int user_id;
|
||||
|
||||
struct list_head list;
|
||||
|
||||
struct list_head kek_list_head;
|
||||
spinlock_t kek_list_lock;
|
||||
}kek_pack_t;
|
||||
|
||||
typedef struct __kek_item {
|
||||
struct list_head list;
|
||||
|
||||
int kek_type;
|
||||
kek_t kek;
|
||||
}kek_item_t;
|
||||
|
||||
#define KEK_PACK_DEBUG 0
|
||||
|
||||
#if KEK_PACK_DEBUG
|
||||
#define KEK_PACK_LOGD(FMT, ...) printk("KEK_PACK[%d] %s :: " FMT , current->pid, __func__, ##__VA_ARGS__)
|
||||
#else
|
||||
#define KEK_PACK_LOGD(FMT, ...)
|
||||
#endif /* PUB_CRYPTO_DEBUG */
|
||||
#define KEK_PACK_LOGE(FMT, ...) printk("KEK_PACK[%d] %s :: " FMT , current->pid, __func__, ##__VA_ARGS__)
|
||||
|
||||
struct list_head kek_pack_list_head;
|
||||
spinlock_t kek_pack_list_lock;
|
||||
spinlock_t del_kek_pack_lock;
|
||||
|
||||
void init_kek_pack(void) {
|
||||
spin_lock_init(&kek_pack_list_lock);
|
||||
spin_lock_init(&del_kek_pack_lock);
|
||||
INIT_LIST_HEAD(&kek_pack_list_head);
|
||||
}
|
||||
|
||||
static kek_pack_t *find_kek_pack(int engine_id) {
|
||||
struct list_head *entry;
|
||||
|
||||
spin_lock(&kek_pack_list_lock);
|
||||
|
||||
list_for_each(entry, &kek_pack_list_head) {
|
||||
kek_pack_t *pack = list_entry(entry, kek_pack_t, list);
|
||||
|
||||
if(pack->engine_id == engine_id) {
|
||||
KEK_PACK_LOGD("Found kek-pack : %d\n", engine_id);
|
||||
spin_unlock(&kek_pack_list_lock);
|
||||
return pack;
|
||||
}
|
||||
}
|
||||
spin_unlock(&kek_pack_list_lock);
|
||||
|
||||
KEK_PACK_LOGE("Can't find kek-pack : %d\n", engine_id);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int __add_kek(kek_pack_t *pack, kek_t *kek, kek_item_t *item) {
|
||||
if(kek == NULL) return -EINVAL;
|
||||
if(pack == NULL) return -EINVAL;
|
||||
|
||||
INIT_LIST_HEAD(&item->list);
|
||||
item->kek_type = kek->type;
|
||||
memcpy(&item->kek, kek, sizeof(kek_t));
|
||||
|
||||
list_add_tail(&item->list, &pack->kek_list_head);
|
||||
|
||||
KEK_PACK_LOGD("item %p\n", item);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static kek_item_t *find_kek_item(kek_pack_t *pack, int kek_type) {
|
||||
struct list_head *entry;
|
||||
|
||||
if(pack == NULL) return NULL;
|
||||
|
||||
list_for_each(entry, &pack->kek_list_head) {
|
||||
kek_item_t *item = list_entry(entry, kek_item_t, list);
|
||||
|
||||
if(item->kek_type == kek_type) {
|
||||
KEK_PACK_LOGD("Found kek-item : %d\n", kek_type);
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
KEK_PACK_LOGD("Can't find kek %d : %d\n", kek_type, pack->engine_id);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void del_kek_item(kek_item_t *item) {
|
||||
KEK_PACK_LOGD("entered\n");
|
||||
|
||||
if(item) {
|
||||
list_del(&item->list);
|
||||
kzfree(item);
|
||||
} else {
|
||||
KEK_PACK_LOGD("given item is NULL\n");
|
||||
}
|
||||
}
|
||||
|
||||
int add_kek_pack(int engine_id, int user_id) {
|
||||
kek_pack_t *new_kek_pack;
|
||||
|
||||
KEK_PACK_LOGD("entered\n");
|
||||
|
||||
if(find_kek_pack(engine_id)) {
|
||||
KEK_PACK_LOGE("kek-pack for %d already exists\n", engine_id);
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
new_kek_pack = kmalloc(sizeof(kek_pack_t), GFP_KERNEL);
|
||||
if(new_kek_pack == NULL) {
|
||||
KEK_PACK_LOGE("can't alloc memory for kek_pack_t\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
new_kek_pack->engine_id = engine_id;
|
||||
new_kek_pack->user_id = user_id;
|
||||
spin_lock_init(&new_kek_pack->kek_list_lock);
|
||||
INIT_LIST_HEAD(&new_kek_pack->kek_list_head);
|
||||
|
||||
spin_lock(&kek_pack_list_lock);
|
||||
list_add_tail(&new_kek_pack->list, &kek_pack_list_head);
|
||||
spin_unlock(&kek_pack_list_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void del_kek_pack(int engine_id) {
|
||||
struct list_head *entry, *q;
|
||||
kek_pack_t *pack;
|
||||
|
||||
spin_lock(&del_kek_pack_lock);
|
||||
KEK_PACK_LOGD("entered\n");
|
||||
pack = find_kek_pack(engine_id);
|
||||
if (pack == NULL) {
|
||||
spin_unlock(&del_kek_pack_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock(&pack->kek_list_lock);
|
||||
list_for_each_safe(entry, q, &pack->kek_list_head) {
|
||||
kek_item_t *item = list_entry(entry, kek_item_t, list);
|
||||
KEK_PACK_LOGD("entry %p item %p\n", entry, item);
|
||||
del_kek_item(item);
|
||||
}
|
||||
spin_unlock(&pack->kek_list_lock);
|
||||
|
||||
list_del(&pack->list);
|
||||
kzfree(pack);
|
||||
spin_unlock(&del_kek_pack_lock);
|
||||
}
|
||||
|
||||
int add_kek(int engine_id, kek_t *kek) {
|
||||
int rc;
|
||||
kek_pack_t *pack;
|
||||
kek_item_t *item;
|
||||
|
||||
item = kmalloc(sizeof(kek_item_t), GFP_KERNEL);
|
||||
if (item == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
spin_lock(&del_kek_pack_lock);
|
||||
KEK_PACK_LOGD("entered\n");
|
||||
pack = find_kek_pack(engine_id);
|
||||
if (pack == NULL) {
|
||||
spin_unlock(&del_kek_pack_lock);
|
||||
kzfree(item);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
spin_lock(&pack->kek_list_lock);
|
||||
if (find_kek_item(pack, kek->type)) {
|
||||
spin_unlock(&pack->kek_list_lock);
|
||||
spin_unlock(&del_kek_pack_lock);
|
||||
kzfree(item);
|
||||
return -EEXIST;
|
||||
}
|
||||
rc = __add_kek(pack, kek, item);
|
||||
|
||||
spin_unlock(&pack->kek_list_lock);
|
||||
spin_unlock(&del_kek_pack_lock);
|
||||
if (rc) {
|
||||
KEK_PACK_LOGE("%s failed. rc = %d", __func__, rc);
|
||||
kzfree(item);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int del_kek(int engine_id, int kek_type) {
|
||||
kek_pack_t *pack;
|
||||
kek_item_t *item;
|
||||
|
||||
KEK_PACK_LOGD("entered\n");
|
||||
|
||||
pack = find_kek_pack(engine_id);
|
||||
if(pack == NULL) return -ENOENT;
|
||||
|
||||
spin_lock(&pack->kek_list_lock);
|
||||
item = find_kek_item(pack, kek_type);
|
||||
if (item == NULL) {
|
||||
spin_unlock(&pack->kek_list_lock);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
del_kek_item(item);
|
||||
spin_unlock(&pack->kek_list_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* I wanted to have some ref-count for kek_item_t that doesn't disturb
|
||||
* ongoing dek process. But the returned kek won't be zero-freed if the process
|
||||
* never returns.
|
||||
*
|
||||
* So allocate new memory and let the user call put accordingly
|
||||
*/
|
||||
kek_t *get_kek(int engine_id, int kek_type, int *rc) {
|
||||
kek_pack_t *pack;
|
||||
kek_item_t *item;
|
||||
kek_t *kek;
|
||||
int userid = current_uid() / PER_USER_RANGE;
|
||||
|
||||
KEK_PACK_LOGD("entered [%d]\n", current_uid());
|
||||
|
||||
pack = find_kek_pack(engine_id);
|
||||
if(pack == NULL) {
|
||||
*rc = -ENOENT;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Across user engine access denied for Knox containers.
|
||||
if(!is_root() &&
|
||||
(pack->user_id >= 100 && pack->user_id < 200) &&
|
||||
(pack->user_id != userid)) {
|
||||
KEK_PACK_LOGE("Permission denied to get kek\n");
|
||||
KEK_PACK_LOGE("pack->user_id[%d] != userid[%d]\n",
|
||||
pack->user_id, userid);
|
||||
|
||||
*rc = -EACCES;
|
||||
return NULL;
|
||||
}
|
||||
kek = kmalloc(sizeof(kek_t), GFP_KERNEL);
|
||||
if (kek == NULL) {
|
||||
*rc = -ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
spin_lock(&pack->kek_list_lock);
|
||||
item = find_kek_item(pack, kek_type);
|
||||
if (item) {
|
||||
*rc = 0;
|
||||
memcpy(kek, &item->kek, sizeof(kek_t));
|
||||
spin_unlock(&pack->kek_list_lock);
|
||||
return kek;
|
||||
} else {
|
||||
spin_unlock(&pack->kek_list_lock);
|
||||
kzfree(kek);
|
||||
}
|
||||
|
||||
*rc = -ENOENT;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void put_kek(kek_t *kek) {
|
||||
KEK_PACK_LOGD("entered\n");
|
||||
|
||||
if(kek) kzfree(kek);
|
||||
}
|
||||
|
||||
int is_kek_pack(int engine_id) {
|
||||
kek_pack_t *pack;
|
||||
|
||||
KEK_PACK_LOGD("entered\n");
|
||||
|
||||
pack = find_kek_pack(engine_id);
|
||||
if(pack) return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int is_kek(int engine_id, int kek_type) {
|
||||
kek_pack_t *pack;
|
||||
kek_item_t *item;
|
||||
|
||||
KEK_PACK_LOGD("entered\n");
|
||||
|
||||
pack = find_kek_pack(engine_id);
|
||||
if(pack == NULL) return 0;
|
||||
|
||||
spin_lock(&pack->kek_list_lock);
|
||||
item = find_kek_item(pack, kek_type);
|
||||
spin_unlock(&pack->kek_list_lock);
|
||||
if(item) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,519 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Sensitive Data Protection
|
||||
*
|
||||
* 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 <crypto/internal/hash.h>
|
||||
#include <crypto/scatterwalk.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/wakelock.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/net.h>
|
||||
#include <net/netlink.h>
|
||||
#include <net/sock.h>
|
||||
#include <net/net_namespace.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/audit.h>
|
||||
#include <linux/jiffies.h>
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <sdp/pub_crypto_emul.h>
|
||||
|
||||
#define NETLINK_FIPS_CRYPTO 29
|
||||
#define PUB_CRYPTO_PID_SET 3001
|
||||
#define PUB_CRYPTO_RESULT 3002
|
||||
|
||||
#define RESULT_ARRAY_MAX_LEN 100
|
||||
|
||||
#define CRYPTO_MAX_TIMEOUT HZ/5
|
||||
|
||||
#define PUB_CRYPTO_REQ_TIMEOUT 3000
|
||||
|
||||
pub_crypto_control_t g_pub_crypto_control;
|
||||
|
||||
DEFINE_MUTEX(crypto_send_mutex);
|
||||
static int user_fipscryptod_pid = 0;
|
||||
static struct sock* crypto_sock = NULL;
|
||||
|
||||
static int pub_crypto_request_get_msg(pub_crypto_request_t *req, char **msg);
|
||||
static void request_send(pub_crypto_control_t *con,
|
||||
pub_crypto_request_t *req);
|
||||
static void request_wait_answer(pub_crypto_control_t *con,
|
||||
pub_crypto_request_t *req);
|
||||
static pub_crypto_request_t *request_find(pub_crypto_control_t *con,
|
||||
u32 request_id);
|
||||
static pub_crypto_request_t *request_alloc(u32 opcode);
|
||||
static void request_free(pub_crypto_control_t *con, pub_crypto_request_t *req);
|
||||
static void req_dump(pub_crypto_request_t *req, const char *msg);
|
||||
static void dump(unsigned char *buf, int len, const char *msg);
|
||||
|
||||
/* Debug */
|
||||
#define PUB_CRYPTO_DEBUG 0
|
||||
|
||||
#if PUB_CRYPTO_DEBUG
|
||||
#define PUB_CRYPTO_LOGD(FMT, ...) printk("SDP_PUB_CRYPTO[%d] : %s " FMT , current->pid, __func__, ##__VA_ARGS__)
|
||||
#else
|
||||
#define PUB_CRYPTO_LOGD(FMT, ...)
|
||||
#endif /* PUB_CRYPTO_DEBUG */
|
||||
#define PUB_CRYPTO_LOGE(FMT, ...) printk("SDP_PUB_CRYPTO[%d] : %s " FMT , current->pid, __func__, ##__VA_ARGS__)
|
||||
#define PUB_CRYPTO_LOGI(FMT, ...) printk("SDP_PUB_CRYPTO[%d] : %s " FMT , current->pid, __func__, ##__VA_ARGS__)
|
||||
|
||||
//static char* process_crypto_request(u8 opcode, char* send_msg,
|
||||
// int send_msg_size, int* result_len, int* ret) {
|
||||
static int __do_dek_crypt(pub_crypto_request_t *req, char *ret) {
|
||||
int rc = 0;
|
||||
|
||||
struct sk_buff *skb_in = NULL;
|
||||
struct sk_buff *skb_out = NULL;
|
||||
struct nlmsghdr *nlh = NULL;
|
||||
|
||||
char *nl_msg = NULL;
|
||||
int nl_msg_size = 0;
|
||||
|
||||
PUB_CRYPTO_LOGD("====================== \t entred\n");
|
||||
|
||||
if(req == NULL) {
|
||||
PUB_CRYPTO_LOGE("invalid request\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
request_send(&g_pub_crypto_control, req);
|
||||
|
||||
nl_msg_size = pub_crypto_request_get_msg(req, &nl_msg);
|
||||
if(nl_msg_size <= 0) {
|
||||
PUB_CRYPTO_LOGE("invalid opcode %d\n", req->opcode);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// sending netlink message
|
||||
skb_in = nlmsg_new(nl_msg_size, 0);
|
||||
if (!skb_in) {
|
||||
PUB_CRYPTO_LOGE("Failed to allocate new skb: \n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
nlh = nlmsg_put(skb_in, 0, 0, NLMSG_DONE, nl_msg_size, 0);
|
||||
NETLINK_CB(skb_in).dst_group = 0;
|
||||
memcpy(nlmsg_data(nlh), nl_msg, nl_msg_size);
|
||||
|
||||
mutex_lock(&crypto_send_mutex);
|
||||
rc = nlmsg_unicast(crypto_sock, skb_in, user_fipscryptod_pid);
|
||||
mutex_unlock(&crypto_send_mutex);
|
||||
|
||||
if (rc < 0) {
|
||||
PUB_CRYPTO_LOGE("Error while sending bak to user, err id: %d\n", rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* In a very rare case, response comes before request gets into pending list.
|
||||
*/
|
||||
if(req->state != PUB_CRYPTO_REQ_FINISHED)
|
||||
request_wait_answer(&g_pub_crypto_control, req);
|
||||
else
|
||||
PUB_CRYPTO_LOGE("request already finished, skip waiting\n");
|
||||
|
||||
skb_out = skb_dequeue(&crypto_sock->sk_receive_queue);
|
||||
|
||||
if(req->state != PUB_CRYPTO_REQ_FINISHED) {
|
||||
PUB_CRYPTO_LOGE("FIPS_CRYPTO_ERROR!!!\n");
|
||||
/*
|
||||
* TODO :
|
||||
* Request not finished by an interrupt or abort.
|
||||
*/
|
||||
rc = -EINTR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(req->aborted) {
|
||||
PUB_CRYPTO_LOGE("Request aborted!!!\n");
|
||||
rc = -ETIMEDOUT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(req->result.ret < 0) {
|
||||
PUB_CRYPTO_LOGE("failed to opcode(%d)!!!\n", req->opcode);
|
||||
rc = req->result.ret;
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch(req->opcode) {
|
||||
case OP_DH_ENC:
|
||||
case OP_DH_DEC:
|
||||
case OP_ECDH_ENC:
|
||||
case OP_ECDH_DEC:
|
||||
dump(req->result.dek.buf, req->result.dek.len, "req->result.dek");
|
||||
memcpy(ret, &(req->result.dek), sizeof(dek_t));
|
||||
//dump(req->result.dek.buf, req->result.dek.len, "req->result.dek");
|
||||
rc = 0;
|
||||
break;
|
||||
case OP_RSA_ENC:
|
||||
case OP_RSA_DEC:
|
||||
memcpy(ret, &(req->result.dek), sizeof(dek_t));
|
||||
rc = 0;
|
||||
break;
|
||||
default:
|
||||
PUB_CRYPTO_LOGE("Not supported opcode(%d)!!!\n", req->opcode);
|
||||
rc = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
if(skb_out) {
|
||||
kfree_skb(skb_out);
|
||||
}
|
||||
if(rc != 0)
|
||||
req_dump(req, "failed");
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static int pub_crypto_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
|
||||
{
|
||||
void *data;
|
||||
u16 msg_type = nlh->nlmsg_type;
|
||||
u32 err = 0;
|
||||
struct audit_status *status_get = NULL;
|
||||
u16 len = 0;
|
||||
|
||||
data = NLMSG_DATA(nlh);
|
||||
len = ntohs(*(uint16_t*) (data+1));
|
||||
switch (msg_type) {
|
||||
case PUB_CRYPTO_PID_SET:
|
||||
status_get = (struct audit_status *)data;
|
||||
user_fipscryptod_pid = status_get->pid;
|
||||
PUB_CRYPTO_LOGE("crypto_receive_msg: pid = %d\n", user_fipscryptod_pid);
|
||||
break;
|
||||
case PUB_CRYPTO_RESULT:
|
||||
{
|
||||
result_t *result = (result_t *)data;
|
||||
pub_crypto_request_t *req = NULL;
|
||||
|
||||
req = request_find(&g_pub_crypto_control, result->request_id);
|
||||
|
||||
if(req) {
|
||||
memcpy(&req->result, result, sizeof(result_t));
|
||||
req->state = PUB_CRYPTO_REQ_FINISHED;
|
||||
wake_up(&req->waitq);
|
||||
|
||||
memset(result, 0, sizeof(result_t));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
PUB_CRYPTO_LOGE("unknown message type : %d\n", msg_type);
|
||||
break;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Receive messages from netlink socket. */
|
||||
static void crypto_recver(struct sk_buff *skb)
|
||||
{
|
||||
struct nlmsghdr *nlh;
|
||||
int len;
|
||||
int err;
|
||||
|
||||
nlh = nlmsg_hdr(skb);
|
||||
len = skb->len;
|
||||
|
||||
err = pub_crypto_recv_msg(skb, nlh);
|
||||
}
|
||||
|
||||
static void dump(unsigned char *buf, int len, const char *msg) {
|
||||
#if PUB_CRYPTO_DEBUG
|
||||
int i;
|
||||
|
||||
printk("%s len=%d: ", msg, len);
|
||||
for(i=0;i<len;++i) {
|
||||
printk("%02x ", (unsigned char)buf[i]);
|
||||
}
|
||||
printk("\n");
|
||||
#else
|
||||
printk("%s len=%d: ", msg, len);
|
||||
printk("\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
int do_dek_crypt(int opcode, dek_t *in, dek_t *out, kek_t *key){
|
||||
pub_crypto_request_t *req = request_alloc(opcode);
|
||||
int ret = -1;
|
||||
|
||||
if(req) {
|
||||
switch(req->opcode) {
|
||||
case OP_RSA_ENC:
|
||||
case OP_RSA_DEC:
|
||||
case OP_DH_ENC:
|
||||
case OP_DH_DEC:
|
||||
case OP_ECDH_ENC:
|
||||
case OP_ECDH_DEC:
|
||||
req->cipher_param.request_id = req->id;
|
||||
req->cipher_param.opcode = req->opcode;
|
||||
memcpy(&req->cipher_param.in, (void *) in, sizeof(dek_t));
|
||||
memcpy(&req->cipher_param.key, (void *) key, sizeof(kek_t));
|
||||
break;
|
||||
default:
|
||||
PUB_CRYPTO_LOGE("opcode[%d] failed, not supported\n", opcode);
|
||||
goto error;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = __do_dek_crypt(req, (char *)out);
|
||||
|
||||
if(ret != 0) {
|
||||
PUB_CRYPTO_LOGE("opcode[%d] failed\n", opcode);
|
||||
goto error;
|
||||
}
|
||||
} else {
|
||||
PUB_CRYPTO_LOGE("request allocation failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
request_free(&g_pub_crypto_control, req);
|
||||
return 0;
|
||||
error:
|
||||
request_free(&g_pub_crypto_control, req);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int rsa_encryptByPub(dek_t *dek, dek_t *edek, kek_t *key){
|
||||
return do_dek_crypt(OP_RSA_ENC, dek, edek, key);
|
||||
}
|
||||
|
||||
int rsa_decryptByPair(dek_t *edek, dek_t *dek, kek_t *key){
|
||||
return do_dek_crypt(OP_RSA_DEC, edek, dek, key);
|
||||
}
|
||||
|
||||
int dh_encryptDEK(dek_t *dek, dek_t *edek, kek_t *key){
|
||||
return do_dek_crypt(OP_DH_ENC, dek, edek, key);
|
||||
}
|
||||
|
||||
int dh_decryptEDEK(dek_t *edek, dek_t *dek, kek_t *key){
|
||||
return do_dek_crypt(OP_DH_DEC, edek, dek, key);
|
||||
}
|
||||
|
||||
int ecdh_encryptDEK(dek_t *dek, dek_t *edek, kek_t *key){
|
||||
return do_dek_crypt(OP_ECDH_ENC, dek, edek, key);
|
||||
}
|
||||
|
||||
int ecdh_decryptEDEK(dek_t *edek, dek_t *dek, kek_t *key){
|
||||
return do_dek_crypt(OP_ECDH_DEC, edek, dek, key);
|
||||
}
|
||||
|
||||
static int pub_crypto_request_get_msg(pub_crypto_request_t *req, char **msg)
|
||||
{
|
||||
int msg_len = -1;
|
||||
|
||||
switch(req->opcode) {
|
||||
case OP_RSA_ENC:
|
||||
case OP_RSA_DEC:
|
||||
case OP_DH_DEC:
|
||||
case OP_DH_ENC:
|
||||
case OP_ECDH_DEC:
|
||||
case OP_ECDH_ENC:
|
||||
*msg = (char *)&req->cipher_param;
|
||||
msg_len = sizeof(cipher_param_t);
|
||||
break;
|
||||
default:
|
||||
*msg = NULL;
|
||||
msg_len = -1;
|
||||
break;
|
||||
}
|
||||
return msg_len;
|
||||
}
|
||||
|
||||
static u32 pub_crypto_get_unique_id(pub_crypto_control_t *control)
|
||||
{
|
||||
spin_lock(&control->lock);
|
||||
|
||||
control->reqctr++;
|
||||
/* zero is special */
|
||||
if (control->reqctr == 0)
|
||||
control->reqctr = 1;
|
||||
|
||||
spin_unlock(&control->lock);
|
||||
|
||||
return control->reqctr;
|
||||
}
|
||||
static void req_dump(pub_crypto_request_t *req, const char *msg) {
|
||||
PUB_CRYPTO_LOGI("req %s {id:%d op:%d state:%d}\n", msg, req->id, req->opcode, req->state);
|
||||
}
|
||||
|
||||
static void request_send(pub_crypto_control_t *con,
|
||||
pub_crypto_request_t *req) {
|
||||
spin_lock(&con->lock);
|
||||
|
||||
list_add_tail(&req->list, &con->pending_list);
|
||||
req->state = PUB_CRYPTO_REQ_PENDING;
|
||||
req_dump(req, "added");
|
||||
|
||||
spin_unlock(&con->lock);
|
||||
}
|
||||
|
||||
static void request_wait_answer(pub_crypto_control_t *con,
|
||||
pub_crypto_request_t *req) {
|
||||
int intr;
|
||||
|
||||
while (req->state != PUB_CRYPTO_REQ_FINISHED) {
|
||||
/*
|
||||
* TODO : can anyone answer what happens when current process gets killed here?
|
||||
*/
|
||||
intr = wait_event_interruptible_timeout(req->waitq,
|
||||
req->state == PUB_CRYPTO_REQ_FINISHED,
|
||||
msecs_to_jiffies(PUB_CRYPTO_REQ_TIMEOUT));
|
||||
if(req->state == PUB_CRYPTO_REQ_FINISHED)
|
||||
break;
|
||||
|
||||
if(intr == 0) {
|
||||
PUB_CRYPTO_LOGE("timeout! %d [ID:%d] \n", intr, req->id);
|
||||
req->state = PUB_CRYPTO_REQ_FINISHED;
|
||||
req->aborted = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if(intr == -ERESTARTSYS) {
|
||||
PUB_CRYPTO_LOGE("wait interrupted : intr %d(-ERESTARTSYS) \n", intr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static pub_crypto_request_t *request_find(pub_crypto_control_t *con,
|
||||
u32 request_id) {
|
||||
struct list_head *entry;
|
||||
|
||||
spin_lock(&con->lock);
|
||||
|
||||
list_for_each(entry, &con->pending_list) {
|
||||
pub_crypto_request_t *req;
|
||||
req = list_entry(entry, pub_crypto_request_t, list);
|
||||
if (req->id == request_id) {
|
||||
req_dump(req, "found");
|
||||
|
||||
spin_unlock(&con->lock);
|
||||
return req;
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock(&con->lock);
|
||||
|
||||
PUB_CRYPTO_LOGE("Can't find request %d\n", request_id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct kmem_cache *pub_crypto_req_cachep;
|
||||
|
||||
static void pub_crypto_request_init(pub_crypto_request_t *req, u32 opcode) {
|
||||
memset(req, 0, sizeof(pub_crypto_request_t));
|
||||
|
||||
req->state = PUB_CRYPTO_REQ_INIT;
|
||||
req->id = pub_crypto_get_unique_id(&g_pub_crypto_control);
|
||||
|
||||
INIT_LIST_HEAD(&req->list);
|
||||
init_waitqueue_head(&req->waitq);
|
||||
atomic_set(&req->count, 1);
|
||||
req->aborted = 0;
|
||||
req->opcode = opcode;
|
||||
}
|
||||
|
||||
static pub_crypto_request_t *request_alloc(u32 opcode) {
|
||||
pub_crypto_request_t *req = kmem_cache_alloc(pub_crypto_req_cachep, GFP_KERNEL);
|
||||
|
||||
if(req)
|
||||
pub_crypto_request_init(req, opcode);
|
||||
return req;
|
||||
}
|
||||
|
||||
static void request_free(pub_crypto_control_t *con, pub_crypto_request_t *req) {
|
||||
if(req) {
|
||||
req_dump(req, "freed");
|
||||
spin_lock(&con->lock);
|
||||
|
||||
list_del(&req->list);
|
||||
memset(req, 0, sizeof(pub_crypto_request_t));
|
||||
kmem_cache_free(pub_crypto_req_cachep, req);
|
||||
|
||||
spin_unlock(&con->lock);
|
||||
} else {
|
||||
PUB_CRYPTO_LOGE("req is NULL, skip free\n");
|
||||
}
|
||||
}
|
||||
|
||||
void pub_crypto_control_init(pub_crypto_control_t *con) {
|
||||
PUB_CRYPTO_LOGD("pub_crypto_control_init");
|
||||
spin_lock_init(&con->lock);
|
||||
INIT_LIST_HEAD(&con->pending_list);
|
||||
con->reqctr = 0;
|
||||
}
|
||||
|
||||
static int __init pub_crypto_mod_init(void) {
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,4,0))
|
||||
struct netlink_kernel_cfg cfg = {
|
||||
.input = crypto_recver,
|
||||
};
|
||||
|
||||
crypto_sock = netlink_kernel_create(&init_net, NETLINK_FIPS_CRYPTO, &cfg);
|
||||
#else
|
||||
crypto_sock = netlink_kernel_create(&init_net, NETLINK_FIPS_CRYPTO, 0, crypto_recver, NULL, THIS_MODULE);
|
||||
#endif
|
||||
|
||||
if (!crypto_sock) {
|
||||
PUB_CRYPTO_LOGE("Failed to create Crypto Netlink Socket .. Exiting \n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
PUB_CRYPTO_LOGE("netlink socket is created successfully! \n");
|
||||
|
||||
pub_crypto_control_init(&g_pub_crypto_control);
|
||||
pub_crypto_req_cachep = kmem_cache_create("pub_crypto_requst",
|
||||
sizeof(pub_crypto_request_t),
|
||||
0, 0, NULL);
|
||||
if (!pub_crypto_req_cachep) {
|
||||
netlink_kernel_release(crypto_sock);
|
||||
PUB_CRYPTO_LOGE("Failed to create pub_crypto_requst cache mem.. Exiting \n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit pub_crypto_mod_exit(void) {
|
||||
|
||||
/*
|
||||
if (crypto_sock && crypto_sock->sk_socket) {
|
||||
sock_release(crypto_sock->sk_socket);
|
||||
}
|
||||
*/
|
||||
netlink_kernel_release(crypto_sock);
|
||||
kmem_cache_destroy(pub_crypto_req_cachep);
|
||||
}
|
||||
|
||||
module_init(pub_crypto_mod_init);
|
||||
module_exit(pub_crypto_mod_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("SDP pub crypto");
|
||||
|
|
@ -1,310 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Sensitive Data Protection
|
||||
*
|
||||
* 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 <linux/debugfs.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <sdp/dlp_ioctl.h>
|
||||
#include <sdp/sdp_dlp.h>
|
||||
|
||||
#define DLP_DUMP_LIST 1 //TODO
|
||||
|
||||
static char *DLP_FILE_EXTENSIONS[] = {"xls", "xlsx", "doc", "docx", "ppt", "pptx", "pdf", "jpg", "jpeg", "zip", "mp4", "txt", "asd", "xlam", "htm", "html", "mht", "eml", "msg", "hwp", "gul", "rtf", "mysingle", "png", "gif"};
|
||||
|
||||
struct dlp_struct {
|
||||
int user_id;
|
||||
long time;
|
||||
bool lock;
|
||||
char* extensions;
|
||||
struct list_head list;
|
||||
struct mutex list_mutex;
|
||||
};
|
||||
struct dlp_struct dlp_info;
|
||||
|
||||
#if DLP_DUMP_LIST
|
||||
static void dlp_dump_list(void) {
|
||||
struct list_head *entry;
|
||||
struct dlp_struct *tmp;
|
||||
|
||||
printk("============ debug ============\n");
|
||||
|
||||
mutex_lock(&dlp_info.list_mutex);
|
||||
|
||||
list_for_each(entry, &dlp_info.list) {
|
||||
tmp = list_entry(entry, struct dlp_struct, list);
|
||||
|
||||
printk("DLP : user_id : %d\n", tmp->user_id);
|
||||
printk("DLP : lock : %s\n", tmp->lock ? "true" : "false");
|
||||
if (tmp->extensions) {
|
||||
printk("DLP : extensions : %s\n", tmp->extensions);
|
||||
} else {
|
||||
printk("DLP : extensions : (empty)\n");
|
||||
}
|
||||
}
|
||||
mutex_unlock(&dlp_info.list_mutex);
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct dlp_struct *dlp_find_list(int user_id) {
|
||||
struct list_head *entry;
|
||||
struct dlp_struct *tmp;
|
||||
|
||||
mutex_lock(&dlp_info.list_mutex);
|
||||
printk("DLP: user_id %d\n", user_id);
|
||||
list_for_each(entry, &dlp_info.list) {
|
||||
tmp = list_entry(entry, struct dlp_struct, list);
|
||||
printk("DLP: tmp->user_id %d\n", tmp->user_id);
|
||||
if(tmp->user_id == user_id) {
|
||||
printk("DLP: found user_id %d\n", user_id); // TODO : deleted
|
||||
mutex_unlock(&dlp_info.list_mutex);
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&dlp_info.list_mutex);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool dlp_is_locked(int user_id) {
|
||||
struct dlp_struct *tmp;
|
||||
tmp = dlp_find_list(user_id);
|
||||
if(tmp){
|
||||
return tmp->lock;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static struct dlp_struct *dlp_add_info(int user_id){
|
||||
struct dlp_struct *new_item;
|
||||
|
||||
new_item = kmalloc(sizeof(struct dlp_struct), GFP_KERNEL);
|
||||
if(new_item == NULL) {
|
||||
printk("DLP: can't alloc memory for dlp_info\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
new_item->user_id = user_id;
|
||||
new_item->lock = false;
|
||||
new_item->extensions = NULL;
|
||||
|
||||
mutex_init(&new_item->list_mutex);
|
||||
INIT_LIST_HEAD(&new_item->list);
|
||||
|
||||
mutex_lock(&dlp_info.list_mutex);
|
||||
list_add_tail(&new_item->list, &dlp_info.list);
|
||||
mutex_unlock(&dlp_info.list_mutex);
|
||||
|
||||
return new_item;
|
||||
}
|
||||
|
||||
static int dlp_lock_setting(void __user *argp, bool lock) {
|
||||
int ret = 0;
|
||||
struct dlp_struct *tmp = NULL;
|
||||
struct _dlp_lock_set dlp_lock_set;
|
||||
|
||||
ret = copy_from_user(&dlp_lock_set, (void __user *)argp, sizeof(dlp_lock_set));
|
||||
if(ret) {
|
||||
printk("DLP : fail to copy_from_user : dlp_lock_setting\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
tmp = dlp_find_list(dlp_lock_set.user_id);
|
||||
if(tmp == NULL){
|
||||
tmp = dlp_add_info(dlp_lock_set.user_id);
|
||||
if(tmp == NULL){
|
||||
return -EFAULT;
|
||||
}
|
||||
}
|
||||
mutex_lock(&dlp_info.list_mutex);
|
||||
tmp->lock = lock;
|
||||
mutex_unlock(&dlp_info.list_mutex);
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
static int dlp_extension_setting(void __user *argp) {
|
||||
int ret = 0;
|
||||
struct dlp_struct *tmp = NULL;
|
||||
struct _dlp_extension_set dlp_ext_set;
|
||||
|
||||
ret = copy_from_user(&dlp_ext_set, (void __user *)argp, sizeof(dlp_ext_set));
|
||||
if(ret) {
|
||||
printk("DLP : fail to copy_from_user : dlp_extension_setting\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
printk("DLP: dlp_extension_setting called with user_id %d\n", dlp_ext_set.user_id);
|
||||
|
||||
tmp = dlp_find_list(dlp_ext_set.user_id);
|
||||
if(tmp == NULL){
|
||||
tmp = dlp_add_info(dlp_ext_set.user_id);
|
||||
if(tmp == NULL){
|
||||
return -EFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Delete old extensions and create new */
|
||||
mutex_lock(&dlp_info.list_mutex);
|
||||
if(tmp->extensions) {
|
||||
kfree(tmp->extensions);
|
||||
tmp->extensions = NULL;
|
||||
}
|
||||
|
||||
if(strlen(dlp_ext_set.extensions)) {
|
||||
tmp->extensions = kmalloc(strlen(dlp_ext_set.extensions)+1, GFP_KERNEL);
|
||||
if (!tmp->extensions) {
|
||||
mutex_unlock(&dlp_info.list_mutex);
|
||||
return -EFAULT;
|
||||
}
|
||||
} else {
|
||||
mutex_unlock(&dlp_info.list_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
strcpy(tmp->extensions, dlp_ext_set.extensions);
|
||||
mutex_unlock(&dlp_info.list_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static long dlp_ioctl(struct file *file, unsigned cmd,
|
||||
unsigned long arg) {
|
||||
int ret = 0;
|
||||
void __user *argp = (void __user *) arg;
|
||||
|
||||
switch (cmd) {
|
||||
case DLP_LOCK_ENABLE: {
|
||||
printk("DLP: DLP_LOCK_ENABLE\n");
|
||||
ret = dlp_lock_setting(argp, true);
|
||||
break;
|
||||
}
|
||||
case DLP_LOCK_DISABLE: {
|
||||
printk("DLP: DLP_LOCK_DISABLE\n");
|
||||
ret = dlp_lock_setting(argp, false);
|
||||
break;
|
||||
}
|
||||
case DLP_EXTENSION_SET: {
|
||||
printk("DLP: DLP_EXTENSION_SET\n");
|
||||
ret = dlp_extension_setting(argp);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
pr_err("DLP : Invalid IOCTL: %d\n", cmd);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#if DLP_DUMP_LIST
|
||||
dlp_dump_list();
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int dlp_isInterestedFile(int user_id, const char *filename){
|
||||
int i, j;
|
||||
char *ext, *ret;
|
||||
char lower[256];
|
||||
struct dlp_struct *item = NULL;
|
||||
ext = strrchr(filename, '.');
|
||||
|
||||
printk("DLP: dlp_isInterestedFile : %s\n", filename);
|
||||
|
||||
if(ext == NULL){
|
||||
printk("DLP: Ext not found\n");
|
||||
return -1;
|
||||
}else{
|
||||
ext++;
|
||||
strncpy(lower, ext, sizeof(lower)-1);
|
||||
lower[sizeof(lower)-1] = '\0';
|
||||
for (j=0; j < strlen(lower); j++) {
|
||||
lower[j] = tolower(lower[j]);
|
||||
}
|
||||
printk("DLP: extension : %s\n", lower);
|
||||
}
|
||||
|
||||
item = dlp_find_list(user_id);
|
||||
if(item == NULL || item->extensions == NULL){
|
||||
//extensions for DLP is not set ...
|
||||
// check if the extension is matching with default extensions
|
||||
printk("DLP: extension set for DLP is not set\n");
|
||||
for(i=(sizeof(DLP_FILE_EXTENSIONS)/sizeof(char*) -1); i>=0; i--){
|
||||
if(strcmp(DLP_FILE_EXTENSIONS[i], lower)==0){
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
printk("DLP: extension not matching with default return -1\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printk("DLP: extension = %s\n", item->extensions);
|
||||
|
||||
strcat(lower, ","); // add comma, so that we compare each ext fully (doc vs. docx)
|
||||
mutex_lock(&dlp_info.list_mutex);
|
||||
ret = strstr(item->extensions, lower);
|
||||
mutex_unlock(&dlp_info.list_mutex);
|
||||
if (ret) {
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
const struct file_operations dlp_fops_evt = {
|
||||
.owner = THIS_MODULE,
|
||||
.unlocked_ioctl = dlp_ioctl,
|
||||
.compat_ioctl = dlp_ioctl,
|
||||
};
|
||||
|
||||
static struct miscdevice dlp_misc_dev = {
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
.name = "sdp_dlp",
|
||||
.fops = &dlp_fops_evt,
|
||||
};
|
||||
|
||||
static int __init dlp_ioctl_init(void) {
|
||||
int ret;
|
||||
|
||||
ret = misc_register(&dlp_misc_dev);
|
||||
if (unlikely(ret)) {
|
||||
printk("DLP: failed to register sdp_dlp device!\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&dlp_info.list);
|
||||
mutex_init(&dlp_info.list_mutex);
|
||||
|
||||
printk("DLP: dlp_ioctl initialized\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit dlp_ioctl_exit(void) {
|
||||
misc_deregister(&dlp_misc_dev);
|
||||
printk("DLP: dlp_ioctl mics_deregister\n");
|
||||
}
|
||||
|
||||
module_init(dlp_ioctl_init);
|
||||
module_exit(dlp_ioctl_exit);
|
|
@ -1,302 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* Sensitive Data Protection
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "SDP_MM: %s: " fmt, __func__
|
||||
|
||||
#include <asm/current.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mm_types.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <sdp/sdp_mm.h>
|
||||
|
||||
#define SDP_MM_DEV "sdp_mm"
|
||||
|
||||
#define SENSITIVE 1
|
||||
#define PER_USER_RANGE 100000
|
||||
|
||||
extern int dek_is_sdp_uid(uid_t uid);
|
||||
|
||||
static struct class *driver_class;
|
||||
static dev_t sdp_mm_device_no;
|
||||
|
||||
struct sdp_mm_control {
|
||||
struct list_head sdp_proc_list_head;
|
||||
spinlock_t sdp_proc_list_lock;
|
||||
struct cdev cdev;
|
||||
unsigned int sensitive_proc_list_len;
|
||||
unsigned int proc_id[MAX_SENSITIVE_PROC];
|
||||
};
|
||||
|
||||
static struct sdp_mm_control sdp_mm;
|
||||
|
||||
static int32_t sdp_mm_query_proc_loaded(void __user *argp)
|
||||
{
|
||||
int32_t ret = 0;
|
||||
struct task_struct *p = NULL;
|
||||
unsigned long flags = 0;
|
||||
struct sdp_mm_sensitive_proc_list_resp sdp_resp = {0};
|
||||
/* foreach process check if 'sensitive' flag is set in task/mm_struct */
|
||||
/* Copy the relevant information needed for loading the image */
|
||||
spin_lock_irqsave(&sdp_mm.sdp_proc_list_lock, flags);
|
||||
for_each_process(p) {
|
||||
if (p->sensitive == SENSITIVE) {
|
||||
sdp_resp.sensitive_proc_list[sdp_resp.sensitive_proc_list_len] = p->pid;
|
||||
sdp_resp.sensitive_proc_list_len++;
|
||||
}
|
||||
if (sdp_resp.sensitive_proc_list_len >= MAX_SENSITIVE_PROC) break;
|
||||
}
|
||||
spin_unlock_irqrestore(&sdp_mm.sdp_proc_list_lock, flags);
|
||||
if (copy_to_user(argp, &sdp_resp, sizeof(sdp_resp))) {
|
||||
pr_err("SDP_MM: copy_to_user_failed\n");
|
||||
ret = -EFAULT;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t sdp_mm_set_process_sensitive(unsigned int proc_id)
|
||||
{
|
||||
int32_t ret = 0;
|
||||
struct task_struct *task = NULL;
|
||||
uid_t uid;
|
||||
|
||||
/* current.task.sensitive = 1 */
|
||||
task = pid_task(find_vpid(proc_id), PIDTYPE_PID);
|
||||
if (task) {
|
||||
uid = task_uid(task);
|
||||
if (((uid/PER_USER_RANGE) <= 199) && ((uid/PER_USER_RANGE) >= 100)) {
|
||||
if (dek_is_sdp_uid(uid)) {
|
||||
task->sensitive = SENSITIVE;
|
||||
printk("SDP_MM: set the process as sensitive\n");
|
||||
} else {
|
||||
printk("SDP_MM: not a SDP process, failed to mark sensitive\n");
|
||||
ret = -EINVAL;
|
||||
goto task_err;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printk("SDP_MM; task not present\n");
|
||||
ret = -EINVAL;
|
||||
goto task_err;
|
||||
}
|
||||
|
||||
task_err:
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(sdp_mm_set_process_sensitive);
|
||||
|
||||
static int32_t sdp_mm_set_proc_sensitive(void __user *argp)
|
||||
{
|
||||
unsigned int proc_id = 0;
|
||||
|
||||
if (copy_from_user(&proc_id, (void __user *)argp,
|
||||
sizeof(unsigned int))) {
|
||||
pr_err("SDP_MM: copy_from_user failed\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
printk("SDP_MM: sensitive process id is %d\n", proc_id);
|
||||
if (sdp_mm.sensitive_proc_list_len < MAX_SENSITIVE_PROC) {
|
||||
sdp_mm.proc_id[sdp_mm.sensitive_proc_list_len] = proc_id;
|
||||
sdp_mm.sensitive_proc_list_len++;
|
||||
}
|
||||
|
||||
return sdp_mm_set_process_sensitive(proc_id);
|
||||
}
|
||||
|
||||
|
||||
static long sdp_mm_ioctl(struct file *file, unsigned cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
int ret = 0;
|
||||
void __user *argp = (void __user *) arg;
|
||||
|
||||
printk("SDP_MM: Entering ioctl\n");
|
||||
|
||||
switch (cmd) {
|
||||
case SDP_MM_IOCTL_PROC_SENSITIVE_QUERY_REQ: {
|
||||
printk("SDP_MM: SENSITIVE_PROC_QUERY\n");
|
||||
ret = sdp_mm_query_proc_loaded(argp);
|
||||
break;
|
||||
}
|
||||
case SDP_MM_IOCTL_SET_SENSITIVE_PROC_REQ: {
|
||||
printk("SDP_MM: SET_PROC_SENSITIVE\n");
|
||||
ret = sdp_mm_set_proc_sensitive(argp);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
pr_err("Invalid IOCTL: %d\n", cmd);
|
||||
return -EINVAL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sdp_mm_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
printk("SDP_MM: entering open\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct file_operations sdp_mm_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.unlocked_ioctl = sdp_mm_ioctl,
|
||||
.open = sdp_mm_open,
|
||||
};
|
||||
|
||||
static int sdp_mm_probe(struct platform_device *pdev)
|
||||
{
|
||||
int rc;
|
||||
struct device *class_dev;
|
||||
|
||||
printk("SDP_MM: entering probe\n");
|
||||
rc = alloc_chrdev_region(&sdp_mm_device_no, 0, 1, SDP_MM_DEV);
|
||||
if (rc < 0) {
|
||||
pr_err("alloc_chrdev_region failed %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
driver_class = class_create(THIS_MODULE, SDP_MM_DEV);
|
||||
if (IS_ERR(driver_class)) {
|
||||
rc = -ENOMEM;
|
||||
pr_err("SDP_MM: class_create failed %d\n", rc);
|
||||
goto exit_unreg_chrdev_region;
|
||||
}
|
||||
|
||||
class_dev = device_create(driver_class, NULL, sdp_mm_device_no, NULL,
|
||||
SDP_MM_DEV);
|
||||
if (!class_dev) {
|
||||
pr_err("SDP_MM: class_device_create failed %d\n", rc);
|
||||
rc = -ENOMEM;
|
||||
goto exit_destroy_class;
|
||||
}
|
||||
|
||||
cdev_init(&sdp_mm.cdev, &sdp_mm_fops);
|
||||
sdp_mm.cdev.owner = THIS_MODULE;
|
||||
|
||||
rc = cdev_add(&sdp_mm.cdev, MKDEV(MAJOR(sdp_mm_device_no), 0), 1);
|
||||
if (rc < 0) {
|
||||
pr_err("SDP_MM: cdev_add failed %d\n", rc);
|
||||
goto exit_destroy_device;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&sdp_mm.sdp_proc_list_head);
|
||||
spin_lock_init(&sdp_mm.sdp_proc_list_lock);
|
||||
|
||||
return 0;
|
||||
|
||||
exit_destroy_device:
|
||||
device_destroy(driver_class, sdp_mm_device_no);
|
||||
exit_destroy_class:
|
||||
class_destroy(driver_class);
|
||||
exit_unreg_chrdev_region:
|
||||
unregister_chrdev_region(sdp_mm_device_no, 1);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int sdp_mm_remove(struct platform_device *pdev)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
cdev_del(&sdp_mm.cdev);
|
||||
device_destroy(driver_class, sdp_mm_device_no);
|
||||
class_destroy(driver_class);
|
||||
unregister_chrdev_region(sdp_mm_device_no, 1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
static struct platform_driver sdp_mm_plat_driver = {
|
||||
.probe = sdp_mm_probe,
|
||||
.remove = sdp_mm_remove,
|
||||
.driver = {
|
||||
.name = "sdp_mm",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init sdp_mm_init(void)
|
||||
{
|
||||
int rc;
|
||||
struct device *class_dev;
|
||||
|
||||
printk("SDP_MM: entering************************************************\n");
|
||||
rc = alloc_chrdev_region(&sdp_mm_device_no, 0, 1, SDP_MM_DEV);
|
||||
if (rc < 0) {
|
||||
pr_err("SDP_MM: Alloc_chrdev_region failed %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
driver_class = class_create(THIS_MODULE, SDP_MM_DEV);
|
||||
if (IS_ERR(driver_class)) {
|
||||
rc = -ENOMEM;
|
||||
pr_err("SDP_MM: class_create failed %d\n", rc);
|
||||
goto exit_unreg_chrdev_region;
|
||||
}
|
||||
|
||||
class_dev = device_create(driver_class, NULL, sdp_mm_device_no, NULL,
|
||||
SDP_MM_DEV);
|
||||
if (!class_dev) {
|
||||
pr_err("SDP_MM: class_device_create failed %d\n", rc);
|
||||
rc = -ENOMEM;
|
||||
goto exit_destroy_class;
|
||||
}
|
||||
|
||||
cdev_init(&sdp_mm.cdev, &sdp_mm_fops);
|
||||
sdp_mm.cdev.owner = THIS_MODULE;
|
||||
|
||||
rc = cdev_add(&sdp_mm.cdev, MKDEV(MAJOR(sdp_mm_device_no), 0), 1);
|
||||
if (rc < 0) {
|
||||
pr_err("SDP_MM: cdev_add failed %d\n", rc);
|
||||
goto exit_destroy_device;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&sdp_mm.sdp_proc_list_head);
|
||||
spin_lock_init(&sdp_mm.sdp_proc_list_lock);
|
||||
return 0;
|
||||
|
||||
exit_destroy_device:
|
||||
device_destroy(driver_class, sdp_mm_device_no);
|
||||
exit_destroy_class:
|
||||
class_destroy(driver_class);
|
||||
exit_unreg_chrdev_region:
|
||||
unregister_chrdev_region(sdp_mm_device_no, 1);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void __exit sdp_mm_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&sdp_mm_plat_driver);
|
||||
}
|
||||
|
||||
module_init(sdp_mm_init);
|
||||
module_exit(sdp_mm_exit);
|
||||
|
||||
MODULE_AUTHOR("HP");
|
||||
MODULE_LICENSE("GPL");
|
Loading…
Reference in a new issue