You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
310 lines
7.3 KiB
310 lines
7.3 KiB
/*
|
|
* 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);
|
|
|