exynos9810: kernel/drivers: remove samsung freecess
This commit is contained in:
parent
1272e07f87
commit
2ffda2a073
8 changed files with 0 additions and 1035 deletions
|
@ -4368,7 +4368,6 @@ CONFIG_ANDROID_LOW_MEMORY_KILLER=y
|
|||
CONFIG_ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES=y
|
||||
CONFIG_ANDROID_INTF_ALARM_DEV=y
|
||||
# CONFIG_ANDROID_VSOC is not set
|
||||
CONFIG_SAMSUNG_FREECESS=y
|
||||
CONFIG_ION=y
|
||||
CONFIG_ION_TEST=y
|
||||
# CONFIG_ION_DUMMY is not set
|
||||
|
|
|
@ -74,9 +74,6 @@
|
|||
#include <uapi/linux/android/binder.h>
|
||||
#include "binder_alloc.h"
|
||||
#include "binder_trace.h"
|
||||
#ifdef CONFIG_SAMSUNG_FREECESS
|
||||
#include <linux/freecess.h>
|
||||
#endif
|
||||
|
||||
int system_server_pid = 0;
|
||||
|
||||
|
@ -3184,13 +3181,6 @@ static void binder_transaction(struct binder_proc *proc,
|
|||
goto err_dead_binder;
|
||||
}
|
||||
e->to_node = target_node->debug_id;
|
||||
#ifdef CONFIG_SAMSUNG_FREECESS
|
||||
if (target_proc
|
||||
&& (target_proc->tsk->cred->euid.val > 10000)
|
||||
&& (proc->pid != target_proc->pid)) {
|
||||
binder_report(proc->tsk, target_proc->tsk, tr->flags & TF_ONE_WAY);
|
||||
}
|
||||
#endif
|
||||
if (security_binder_transaction(proc->tsk,
|
||||
target_proc->tsk) < 0) {
|
||||
return_error = BR_FAILED_REPLY;
|
||||
|
@ -5822,81 +5812,6 @@ static void print_binder_proc(struct seq_file *m,
|
|||
m->count = start_pos;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SAMSUNG_FREECESS
|
||||
static void binder_in_transaction(struct binder_proc *proc)
|
||||
{
|
||||
struct rb_node *n = NULL;
|
||||
struct binder_thread *thread = NULL;
|
||||
int uid = -1;
|
||||
struct task_struct *tsk = NULL;
|
||||
struct binder_transaction *t = NULL;
|
||||
bool empty = true;
|
||||
bool found = false;
|
||||
|
||||
//check binder threads todo and transcation_stack list
|
||||
binder_inner_proc_lock(proc);
|
||||
for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n)) {
|
||||
thread = rb_entry(n, struct binder_thread, rb_node);
|
||||
empty = binder_worklist_empty_ilocked(&thread->todo);
|
||||
tsk = thread->task;
|
||||
|
||||
if (tsk != NULL) {
|
||||
//have some binders to do
|
||||
if (!empty) {
|
||||
//report uid to FW, only report one time
|
||||
uid = tsk->cred->euid.val;
|
||||
binder_inner_proc_unlock(proc);
|
||||
cfb_report(uid, "thread");
|
||||
return;
|
||||
}
|
||||
|
||||
//processing one binder call
|
||||
t = thread->transaction_stack;
|
||||
if (t) {
|
||||
spin_lock(&t->lock);
|
||||
if (t->to_thread == thread) {
|
||||
//check incoming, it has one
|
||||
found = true;
|
||||
uid = tsk->cred->euid.val;
|
||||
}
|
||||
spin_unlock(&t->lock);
|
||||
if (found == true){
|
||||
//report uid to FW, only report one time
|
||||
binder_inner_proc_unlock(proc);
|
||||
cfb_report(uid, "transaction_stack");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//check binder proc todo list
|
||||
empty = binder_worklist_empty_ilocked(&proc->todo);
|
||||
tsk = proc->tsk;
|
||||
if (tsk != NULL && !empty) {
|
||||
//report uid to FW
|
||||
uid = tsk->cred->euid.val;
|
||||
binder_inner_proc_unlock(proc);
|
||||
cfb_report(uid, "proc");
|
||||
}
|
||||
else
|
||||
binder_inner_proc_unlock(proc);
|
||||
}
|
||||
|
||||
void binders_in_transcation(int uid)
|
||||
{
|
||||
struct binder_proc *itr;
|
||||
|
||||
mutex_lock(&binder_procs_lock);
|
||||
hlist_for_each_entry(itr, &binder_procs, proc_node) {
|
||||
if (itr != NULL && (itr->tsk->cred->euid.val == uid)) {
|
||||
binder_in_transaction(itr);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&binder_procs_lock);
|
||||
}
|
||||
#endif
|
||||
|
||||
static const char * const binder_return_strings[] = {
|
||||
"BR_ERROR",
|
||||
"BR_OK",
|
||||
|
|
|
@ -51,12 +51,6 @@ config ANDROID_VSOC
|
|||
a 'cuttlefish' Android image inside QEmu. The driver interacts with
|
||||
a QEmu ivshmem device. If built as a module, it will be called vsoc.
|
||||
|
||||
config SAMSUNG_FREECESS
|
||||
bool "thraw frozen process when recv sig"
|
||||
default n
|
||||
help
|
||||
thraw frozen process when recv sig.
|
||||
|
||||
source "drivers/staging/android/ion/Kconfig"
|
||||
source "drivers/staging/android/switch/Kconfig"
|
||||
|
||||
|
|
|
@ -7,5 +7,3 @@ obj-$(CONFIG_ANDROID_LOW_MEMORY_KILLER) += lowmemorykiller.o
|
|||
obj-$(CONFIG_ANDROID_INTF_ALARM_DEV) += alarm-dev.o
|
||||
obj-$(CONFIG_ANDROID_SWITCH) += switch/
|
||||
obj-$(CONFIG_ANDROID_VSOC) += vsoc.o
|
||||
obj-$(CONFIG_SAMSUNG_FREECESS) += freecess.o
|
||||
obj-$(CONFIG_SAMSUNG_FREECESS) += freecess_pkg.o
|
||||
|
|
|
@ -1,608 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) Samsung Technologies Co., Ltd. 2001-2017. All rights reserved.
|
||||
*
|
||||
* File name: freecess.c
|
||||
* Description: Use to thaw process from state 'D'
|
||||
* Author: chao.gu@samsung.com
|
||||
* Version: 0.2
|
||||
* Date: 2017/07/17
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/freecess.h>
|
||||
#include <linux/freezer.h>
|
||||
#include <net/sock.h>
|
||||
#include <linux/hrtimer.h>
|
||||
#include <linux/proc_fs.h>
|
||||
|
||||
|
||||
#define RET_OK 0
|
||||
#define RET_ERR 1
|
||||
static struct sock *kfreecess_mod_sock = NULL;
|
||||
static atomic_t bind_port[MOD_END];
|
||||
static atomic_t kfreecess_init_suc;
|
||||
static int last_kill_pid = -1;
|
||||
static struct proc_dir_entry *freecess_rootdir = NULL;
|
||||
|
||||
struct report_stat_s
|
||||
{
|
||||
spinlock_t lock;
|
||||
struct {
|
||||
u64 report_suc_count;
|
||||
u64 report_fail_count;
|
||||
u64 total_runtime;
|
||||
|
||||
u64 report_suc_from_windowstart;
|
||||
u64 report_fail_from_windowstart;
|
||||
u64 runtime_from_windowstart;
|
||||
}data;
|
||||
char name[32];
|
||||
};
|
||||
|
||||
struct freecess_info_s
|
||||
{
|
||||
struct report_stat_s mod_reportstat[MOD_END];
|
||||
} freecess_info;
|
||||
|
||||
static char* mod_name[MOD_END] =
|
||||
{
|
||||
"NULL",
|
||||
"MOD_BINDER",
|
||||
"MOD_SIG",
|
||||
"MOD_PKG",
|
||||
"MOD_CFB"
|
||||
};
|
||||
|
||||
struct priv_data
|
||||
{
|
||||
int caller_pid;
|
||||
int target_uid;
|
||||
int flag; //MOD_SIG,MOD_BINDER
|
||||
pkg_info_t pkg_info; //MOD_PKG
|
||||
};
|
||||
|
||||
static freecess_hook mod_recv_handler[MOD_END];
|
||||
|
||||
static int check_msg_type(int type)
|
||||
{
|
||||
return (type < MSG_TYPE_END) && (type > 0);
|
||||
}
|
||||
|
||||
static int check_mod_type(int mod)
|
||||
{
|
||||
return (mod < MOD_END) && (mod > 0);
|
||||
}
|
||||
|
||||
static int thread_group_is_frozen(struct task_struct* task)
|
||||
{
|
||||
struct task_struct *leader = task->group_leader;
|
||||
|
||||
return (freezing(leader) || frozen(leader));
|
||||
}
|
||||
|
||||
static void dump_kfreecess_msg(struct kfreecess_msg_data *msg)
|
||||
{
|
||||
printk(KERN_ERR "-----kfreecess msg dump-----\n");
|
||||
if (!msg) {
|
||||
printk(KERN_ERR "msg is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
printk(KERN_ERR "type: %d, mode: %d\n", msg->type, msg->mod);
|
||||
}
|
||||
|
||||
|
||||
int mod_sendmsg(int type, int mod, struct priv_data* data)
|
||||
{
|
||||
int ret, msg_len = 0;
|
||||
struct sk_buff *skb = NULL;
|
||||
struct nlmsghdr *nlh = NULL;
|
||||
struct kfreecess_msg_data *payload = NULL;
|
||||
|
||||
if (!atomic_read(&kfreecess_init_suc))
|
||||
return RET_ERR;
|
||||
|
||||
if (!check_msg_type(type)) {
|
||||
pr_err("%s: msg type is invalid! %d\n", __func__, type);
|
||||
return RET_ERR;
|
||||
}
|
||||
|
||||
if (!check_mod_type(mod)) {
|
||||
pr_err("%s: mod type is invalid! %d\n", __func__, mod);
|
||||
return RET_ERR;
|
||||
}
|
||||
|
||||
msg_len = sizeof(struct kfreecess_msg_data);
|
||||
skb = nlmsg_new(msg_len, GFP_ATOMIC);
|
||||
if (!skb) {
|
||||
pr_err("%s alloc_skb failed! %d\n", __func__, mod);
|
||||
return RET_ERR;
|
||||
}
|
||||
|
||||
nlh = nlmsg_put(skb, 0, 0, 0, msg_len, 0);
|
||||
if (!nlh) {
|
||||
kfree_skb(skb);
|
||||
return RET_ERR;
|
||||
}
|
||||
|
||||
payload = nlmsg_data(nlh);
|
||||
payload->type = type;
|
||||
payload->mod = mod;
|
||||
payload->src_portid = KERNEL_ID_NETLINK;
|
||||
payload->dst_portid = atomic_read(&bind_port[mod]);
|
||||
|
||||
if (data) {
|
||||
payload->caller_pid = data->caller_pid;
|
||||
payload->target_uid = data->target_uid;
|
||||
if (payload->mod == MOD_PKG)
|
||||
memcpy(&payload->pkg_info, &data->pkg_info, sizeof(pkg_info_t));
|
||||
else
|
||||
payload->flag = data->flag;
|
||||
}
|
||||
//dump_kfreecess_msg(payload);
|
||||
if ((ret = nlmsg_unicast(kfreecess_mod_sock, skb, payload->dst_portid)) < 0) {
|
||||
pr_err("nlmsg_unicast failed! %s errno %d\n", __func__ , ret);
|
||||
return RET_ERR;
|
||||
} else
|
||||
pr_info("nlmsg_unicast snd msg success\n");
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int sig_report(struct task_struct *caller, struct task_struct *p)
|
||||
{
|
||||
int ret = RET_OK;
|
||||
struct priv_data data;
|
||||
int target_pid = task_tgid_nr(p);
|
||||
u64 walltime, timecost;
|
||||
unsigned long flags;
|
||||
struct report_stat_s *stat;
|
||||
|
||||
walltime = ktime_to_us(ktime_get());
|
||||
memset(&data, 0, sizeof(struct priv_data));
|
||||
data.caller_pid = task_tgid_nr(caller);
|
||||
data.target_uid = task_uid(p).val;
|
||||
data.flag = 0;
|
||||
|
||||
if (thread_group_is_frozen(p) && (target_pid != last_kill_pid)) {
|
||||
last_kill_pid = target_pid;
|
||||
stat = &freecess_info.mod_reportstat[MOD_SIG];
|
||||
ret = mod_sendmsg(MSG_TO_USER, MOD_SIG, &data);
|
||||
|
||||
spin_lock_irqsave(&stat->lock, flags);
|
||||
if (ret < 0) {
|
||||
stat->data.report_fail_count++;
|
||||
stat->data.report_fail_from_windowstart++;
|
||||
pr_err("sig_report error\n");
|
||||
} else {
|
||||
stat->data.report_suc_count++;
|
||||
stat->data.report_suc_from_windowstart++;
|
||||
}
|
||||
|
||||
timecost = ktime_to_us(ktime_get()) - walltime;
|
||||
stat->data.total_runtime += timecost;
|
||||
stat->data.runtime_from_windowstart += timecost;
|
||||
spin_unlock_irqrestore(&stat->lock, flags);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int binder_report(struct task_struct *caller, struct task_struct *p, int flag)
|
||||
{
|
||||
int ret = RET_OK;
|
||||
struct priv_data data;
|
||||
u64 walltime, timecost;
|
||||
unsigned long flags;
|
||||
struct report_stat_s *stat;
|
||||
|
||||
memset(&data, 0, sizeof(struct priv_data));
|
||||
data.target_uid = -1;
|
||||
data.caller_pid = -1;
|
||||
data.flag = flag;
|
||||
|
||||
if(p)
|
||||
data.target_uid = task_uid(p).val;
|
||||
if(caller)
|
||||
data.caller_pid = task_tgid_nr(caller);
|
||||
|
||||
walltime = ktime_to_us(ktime_get());
|
||||
if (p && thread_group_is_frozen(p)) {
|
||||
ret = mod_sendmsg(MSG_TO_USER, MOD_BINDER, &data);
|
||||
stat = &freecess_info.mod_reportstat[MOD_BINDER];
|
||||
spin_lock_irqsave(&stat->lock, flags);
|
||||
if (ret < 0) {
|
||||
stat->data.report_fail_count++;
|
||||
stat->data.report_fail_from_windowstart++;
|
||||
pr_err("binder_report error\n");
|
||||
} else {
|
||||
stat->data.report_suc_count++;
|
||||
stat->data.report_suc_from_windowstart++;
|
||||
}
|
||||
|
||||
timecost = ktime_to_us(ktime_get()) - walltime;
|
||||
stat->data.total_runtime += timecost;
|
||||
stat->data.runtime_from_windowstart += timecost;
|
||||
spin_unlock_irqrestore(&stat->lock, flags);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int pkg_report(int target_uid)
|
||||
{
|
||||
int ret = RET_OK;
|
||||
struct priv_data data;
|
||||
u64 walltime, timecost;
|
||||
unsigned long flags;
|
||||
struct report_stat_s *stat;
|
||||
|
||||
memset(&data, 0, sizeof(struct priv_data));
|
||||
data.target_uid = target_uid;
|
||||
data.pkg_info.uid = (uid_t)target_uid;
|
||||
walltime = ktime_to_us(ktime_get());
|
||||
ret = mod_sendmsg(MSG_TO_USER, MOD_PKG, &data);
|
||||
stat = &freecess_info.mod_reportstat[MOD_PKG];
|
||||
spin_lock_irqsave(&stat->lock, flags);
|
||||
if (ret < 0) {
|
||||
stat->data.report_fail_count++;
|
||||
stat->data.report_fail_from_windowstart++;
|
||||
} else {
|
||||
stat->data.report_suc_count++;
|
||||
stat->data.report_suc_from_windowstart++;
|
||||
}
|
||||
|
||||
timecost = ktime_to_us(ktime_get()) - walltime;
|
||||
stat->data.total_runtime += timecost;
|
||||
stat->data.runtime_from_windowstart += timecost;
|
||||
spin_unlock_irqrestore(&stat->lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cfb_report(int target_uid, const char *reason)
|
||||
{
|
||||
int ret = RET_OK;
|
||||
struct priv_data data;
|
||||
|
||||
printk(KERN_INFO "cfb_report: uid %d frozen, reason: %s\n", target_uid, reason);
|
||||
memset(&data, 0, sizeof(struct priv_data));
|
||||
data.target_uid = target_uid;
|
||||
ret = mod_sendmsg(MSG_TO_USER, MOD_CFB, &data);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void recv_handler(struct sk_buff *skb)
|
||||
{
|
||||
struct kfreecess_msg_data *payload = NULL;
|
||||
struct nlmsghdr *nlh = NULL;
|
||||
unsigned int msglen = 0;
|
||||
uid_t uid = 0;
|
||||
|
||||
if (!skb) {
|
||||
pr_err("recv_handler %s: skb is NULL!\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
uid = (*NETLINK_CREDS(skb)).uid.val;
|
||||
//only allow system user to communicate with Freecess kernel part.
|
||||
if (uid != 1000) {
|
||||
pr_err("freecess--uid: %d, permission denied\n", uid);
|
||||
return;
|
||||
}
|
||||
printk(KERN_ERR "kernel freecess receive msg now\n");
|
||||
if (skb->len >= NLMSG_SPACE(0)) {
|
||||
nlh = nlmsg_hdr(skb);
|
||||
msglen = NLMSG_PAYLOAD(nlh, 0);
|
||||
payload = (struct kfreecess_msg_data*)NLMSG_DATA(nlh);
|
||||
|
||||
if (msglen >= (sizeof(struct kfreecess_msg_data))) {
|
||||
if (payload->src_portid < 0) {
|
||||
pr_err("USER_HOOK_CALLBACK %s: src_portid %d is not valid!\n", __func__, payload->src_portid);
|
||||
return;
|
||||
}
|
||||
|
||||
if (payload->dst_portid != KERNEL_ID_NETLINK) {
|
||||
pr_err("USER_HOOK_CALLBACK %s: dst_portid is %d not kernel!\n", __func__, payload->dst_portid);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!check_mod_type(payload->mod)) {
|
||||
pr_err("USER_HOOK_CALLBACK %s: mod %d is not valid!\n", __func__, payload->mod);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (payload->type) {
|
||||
case LOOPBACK_MSG:
|
||||
atomic_set(&bind_port[payload->mod], payload->src_portid);
|
||||
dump_kfreecess_msg(payload);
|
||||
mod_sendmsg(LOOPBACK_MSG, payload->mod, NULL);
|
||||
break;
|
||||
case MSG_TO_KERN:
|
||||
if (mod_recv_handler[payload->mod])
|
||||
mod_recv_handler[payload->mod](payload, sizeof(struct kfreecess_msg_data));
|
||||
else
|
||||
dump_kfreecess_msg(payload);
|
||||
break;
|
||||
|
||||
default:
|
||||
pr_err("msg type is valid %d\n", payload->type);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
pr_err("%s: length err msglen %d struct kfreecess_msg_data %lu!\n", __func__, msglen, sizeof(struct kfreecess_msg_data));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*proc and sysctl interface*/
|
||||
static int freecess_window_stat_show(struct seq_file *m, void *v)
|
||||
{
|
||||
int i;
|
||||
unsigned long flags;
|
||||
struct report_stat_s *stat;
|
||||
struct freecess_info_s tmp_freecess_info;
|
||||
struct report_stat_s total_stat;
|
||||
|
||||
memset(&tmp_freecess_info, 0, sizeof(struct freecess_info_s));
|
||||
memset(&total_stat, 0, sizeof(struct report_stat_s));
|
||||
for(i = 1; i < MOD_END; i++) {
|
||||
stat = &freecess_info.mod_reportstat[i];
|
||||
spin_lock_irqsave(&stat->lock, flags);
|
||||
tmp_freecess_info.mod_reportstat[i].data = stat->data;
|
||||
spin_unlock_irqrestore(&stat->lock, flags);
|
||||
strlcpy(tmp_freecess_info.mod_reportstat[i].name, stat->name, 32);
|
||||
}
|
||||
|
||||
seq_printf(m, "freecess window stat show\n");
|
||||
seq_printf(m, "-----------------------------\n\n");
|
||||
for(i = 1; i < MOD_END; i++) {
|
||||
stat = &tmp_freecess_info.mod_reportstat[i];
|
||||
total_stat.data.report_suc_from_windowstart += stat->data.report_suc_from_windowstart;
|
||||
total_stat.data.report_fail_from_windowstart += stat->data.report_fail_from_windowstart;
|
||||
total_stat.data.runtime_from_windowstart += stat->data.runtime_from_windowstart;
|
||||
|
||||
seq_printf(m, "mod name: %s mod number %d:\n", stat->name, i);
|
||||
seq_printf(m, "suc_count: %llu\n", stat->data.report_suc_from_windowstart);
|
||||
seq_printf(m, "fail_count: %llu\n", stat->data.report_fail_from_windowstart);
|
||||
seq_printf(m, "total_runtime: %llu us\n\n", stat->data.runtime_from_windowstart);
|
||||
|
||||
}
|
||||
|
||||
stat = &total_stat;
|
||||
seq_printf(m, "info of all mod\n");
|
||||
seq_printf(m, "-----------------------------\n");
|
||||
seq_printf(m, "suc_count: %llu\n", stat->data.report_suc_from_windowstart);
|
||||
seq_printf(m, "fail_count: %llu\n", stat->data.report_fail_from_windowstart);
|
||||
seq_printf(m, "total_runtime: %llu us\n", stat->data.runtime_from_windowstart);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int freecess_window_stat_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, freecess_window_stat_show, NULL);
|
||||
}
|
||||
|
||||
static void reset_window(void)
|
||||
{
|
||||
int i;
|
||||
unsigned long flags;
|
||||
struct report_stat_s *stat;
|
||||
|
||||
for(i = 1; i < MOD_END; i++) {
|
||||
stat = &freecess_info.mod_reportstat[i];
|
||||
spin_lock_irqsave(&stat->lock, flags);
|
||||
stat->data.report_suc_from_windowstart = 0;
|
||||
stat->data.report_fail_from_windowstart = 0;
|
||||
stat->data.runtime_from_windowstart = 0;
|
||||
spin_unlock_irqrestore(&stat->lock, flags);
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t freecess_window_stat_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_ops)
|
||||
{
|
||||
unsigned char tmp = 0;
|
||||
int value = 0;
|
||||
|
||||
get_user(tmp, buf);
|
||||
value = simple_strtol(&tmp, NULL, 10);
|
||||
printk(KERN_WARNING "input value number: %d, if value == 1: window will reset ....\n", value);
|
||||
if (value == 1)
|
||||
reset_window();
|
||||
|
||||
printk(KERN_WARNING "window reset now\n");
|
||||
return count;
|
||||
|
||||
}
|
||||
|
||||
static const struct file_operations window_stat_proc_fops = {
|
||||
.open = freecess_window_stat_open,
|
||||
.read = seq_read,
|
||||
.write = freecess_window_stat_write,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int pkg_stat_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, pkg_stat_show, NULL);
|
||||
}
|
||||
|
||||
static const struct file_operations pkg_stat_proc_fops = {
|
||||
.open = pkg_stat_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static int freecess_modstat_show(struct seq_file *m, void *v)
|
||||
{
|
||||
int i;
|
||||
unsigned long flags;
|
||||
struct report_stat_s *stat;
|
||||
static struct freecess_info_s tmp_freecess_info;
|
||||
struct report_stat_s total_stat;
|
||||
|
||||
memset(&tmp_freecess_info, 0, sizeof(struct freecess_info_s));
|
||||
memset(&total_stat, 0, sizeof(struct report_stat_s));
|
||||
for(i = 1; i < MOD_END; i++) {
|
||||
stat = &freecess_info.mod_reportstat[i];
|
||||
spin_lock_irqsave(&stat->lock, flags);
|
||||
tmp_freecess_info.mod_reportstat[i].data = stat->data;
|
||||
spin_unlock_irqrestore(&stat->lock, flags);
|
||||
strlcpy(tmp_freecess_info.mod_reportstat[i].name, stat->name, 32);
|
||||
}
|
||||
|
||||
seq_printf(m, "freecess mod stat show\n");
|
||||
seq_printf(m, "-----------------------------\n\n");
|
||||
for(i = 1; i < MOD_END; i++) {
|
||||
stat = &tmp_freecess_info.mod_reportstat[i];
|
||||
total_stat.data.report_suc_count += stat->data.report_suc_count;
|
||||
total_stat.data.report_fail_count += stat->data.report_fail_count;
|
||||
total_stat.data.total_runtime += stat->data.total_runtime;
|
||||
|
||||
seq_printf(m, "mod name: %s mod number %d:\n", stat->name, i);
|
||||
seq_printf(m, "suc_count: %llu\n", stat->data.report_suc_count);
|
||||
seq_printf(m, "fail_count: %llu\n", stat->data.report_fail_count);
|
||||
seq_printf(m, "total_runtime: %llu us\n\n", stat->data.total_runtime);
|
||||
}
|
||||
|
||||
stat = &total_stat;
|
||||
seq_printf(m, "info of all mod:\n");
|
||||
seq_printf(m, "suc_count: %llu\n", stat->data.report_suc_count);
|
||||
seq_printf(m, "fail_count: %llu\n", stat->data.report_fail_count);
|
||||
seq_printf(m, "total_runtime: %llu us\n", stat->data.total_runtime);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int freecess_mod_stat_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, freecess_modstat_show, NULL);
|
||||
}
|
||||
|
||||
static const struct file_operations mod_stat_proc_fops = {
|
||||
.open = freecess_mod_stat_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static void freecess_runinfo_init(struct freecess_info_s *f)
|
||||
{
|
||||
int i;
|
||||
struct report_stat_s *stat;
|
||||
|
||||
for(i = 1; i < MOD_END; i++) {
|
||||
stat = &f->mod_reportstat[i];
|
||||
spin_lock_init(&stat->lock);
|
||||
stat->data.report_suc_count = 0;
|
||||
stat->data.report_fail_count = 0;
|
||||
stat->data.total_runtime = 0;
|
||||
stat->data.report_suc_from_windowstart = 0;
|
||||
stat->data.report_fail_from_windowstart = 0;
|
||||
stat->data.runtime_from_windowstart = 0;
|
||||
strlcpy(f->mod_reportstat[i].name, mod_name[i], 32);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int register_kfreecess_hook(int mod, freecess_hook hook)
|
||||
{
|
||||
|
||||
if (!check_mod_type(mod)) {
|
||||
pr_err("%s: mod type is invalid! %d\n", __func__, mod);
|
||||
return RET_ERR;
|
||||
}
|
||||
|
||||
if (hook)
|
||||
mod_recv_handler[mod] = hook;
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int unregister_kfreecess_hook(int mod)
|
||||
{
|
||||
if (!check_mod_type(mod)) {
|
||||
pr_err("%s: mod type is invalid! %d\n", __func__, mod);
|
||||
return RET_ERR;
|
||||
}
|
||||
mod_recv_handler[mod] = NULL;
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
static int __init kfreecess_init(void)
|
||||
{
|
||||
int ret = RET_ERR;
|
||||
struct proc_dir_entry *freecess_modstat_entry = NULL;
|
||||
struct proc_dir_entry *freecess_window_stat_entry = NULL;
|
||||
struct proc_dir_entry *pkg_modstat_entry = NULL;
|
||||
int i;
|
||||
|
||||
struct netlink_kernel_cfg cfg = {
|
||||
.input = recv_handler,
|
||||
};
|
||||
kfreecess_mod_sock = netlink_kernel_create(&init_net, NETLINK_KFREECESS, &cfg);
|
||||
if (!kfreecess_mod_sock) {
|
||||
pr_err("%s: create kfreecess_mod_sock socket error!\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
for(i = 1; i<MOD_END; i++)
|
||||
atomic_set(&bind_port[i], 0);
|
||||
|
||||
|
||||
freecess_rootdir = proc_mkdir("freecess", NULL);
|
||||
if (!freecess_rootdir)
|
||||
pr_err("create /proc/freecess failed\n");
|
||||
else {
|
||||
freecess_window_stat_entry = proc_create("windowstat", 0644, freecess_rootdir, &window_stat_proc_fops);
|
||||
if (!freecess_window_stat_entry) {
|
||||
pr_err("create /proc/freecess/windowstat failed, remove /proc/freecess dir\n");
|
||||
remove_proc_entry("freecess", NULL);
|
||||
freecess_rootdir = NULL;
|
||||
} else {
|
||||
freecess_modstat_entry = proc_create("modstat", 0, freecess_rootdir, &mod_stat_proc_fops);
|
||||
if (!freecess_modstat_entry) {
|
||||
pr_err("create /proc/freecess/modstat failed, remove /proc/freecess dir\n");
|
||||
remove_proc_entry("freecess/windowstat", NULL);
|
||||
remove_proc_entry("freecess", NULL);
|
||||
freecess_rootdir = NULL;
|
||||
} else {
|
||||
pkg_modstat_entry = proc_create("pkgstat", 0, freecess_rootdir, &pkg_stat_proc_fops);
|
||||
if (!pkg_modstat_entry) {
|
||||
pr_err("create /proc/freecess/pkgstat failed, remove /proc/freecess dir\n");
|
||||
remove_proc_entry("freecess/windowstat", NULL);
|
||||
remove_proc_entry("freecess/modstat", NULL);
|
||||
remove_proc_entry("freecess", NULL);
|
||||
freecess_rootdir = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
freecess_runinfo_init(&freecess_info);
|
||||
atomic_set(&kfreecess_init_suc, 1);
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
static void __exit kfreecess_exit(void)
|
||||
{
|
||||
if (kfreecess_mod_sock)
|
||||
netlink_kernel_release(kfreecess_mod_sock);
|
||||
|
||||
if (freecess_rootdir) {
|
||||
remove_proc_entry("windowstat", freecess_rootdir);
|
||||
remove_proc_entry("modstat", freecess_rootdir);
|
||||
remove_proc_entry("pkgstat", freecess_rootdir);
|
||||
remove_proc_entry("freecess", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
module_init(kfreecess_init);
|
||||
module_exit(kfreecess_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
|
@ -1,286 +0,0 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netfilter_ipv4.h>
|
||||
#include <linux/netfilter_ipv6.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/rbtree.h>
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/types.h>
|
||||
#include <net/sock.h>
|
||||
#include <net/ip.h>
|
||||
#include <net/tcp.h>
|
||||
#include <net/inet_hashtables.h>
|
||||
#include <net/inet6_hashtables.h>
|
||||
#include <linux/freecess.h>
|
||||
|
||||
|
||||
#define MAX_REC_UID 64
|
||||
static atomic_t uid_rec[MAX_REC_UID];
|
||||
extern void binders_in_transcation(int uid);
|
||||
|
||||
int pkg_stat_show(struct seq_file *m, void *v)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_REC_UID; i++)
|
||||
if (atomic_read(&uid_rec[i]))
|
||||
seq_printf(m, "%d\t", atomic_read(&uid_rec[i]));
|
||||
seq_printf(m, "\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void freecess_add_uid(uid_t uid)
|
||||
{
|
||||
int i, j;
|
||||
uid_t inner_uid;
|
||||
|
||||
for (i = 0, j = MAX_REC_UID; i < MAX_REC_UID; i++) {
|
||||
inner_uid = atomic_read(&uid_rec[i]);
|
||||
if (inner_uid == 0 && j == MAX_REC_UID)
|
||||
j = i;
|
||||
else if (inner_uid == uid)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (j < MAX_REC_UID)
|
||||
atomic_set(&uid_rec[j], uid);
|
||||
else
|
||||
pr_err("%s : add uid:%d failed (full)!\n", __func__, uid);
|
||||
out:
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void freecess_del_uid(uid_t uid)
|
||||
{
|
||||
int i;
|
||||
uid_t inner_uid;
|
||||
|
||||
for (i = 0; i < MAX_REC_UID; i++) {
|
||||
inner_uid = (uid_t)atomic_read(&uid_rec[i]);
|
||||
if (inner_uid == uid) {
|
||||
atomic_set(&uid_rec[i], 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void freecess_clear_all(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_REC_UID; i++) {
|
||||
atomic_set(&uid_rec[i], 0);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int find_and_clear_uid(uid_t uid)
|
||||
{
|
||||
int found = 0;
|
||||
int i = 0;
|
||||
uid_t inner_uid;
|
||||
|
||||
for (i = 0; i < MAX_REC_UID; i++) {
|
||||
inner_uid = atomic_read(&uid_rec[i]);
|
||||
if (unlikely (inner_uid == uid)) {
|
||||
if (atomic_cmpxchg(&uid_rec[i], uid, 0) == uid)
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
static void kfreecess_pkg_hook(void* data, unsigned int len)
|
||||
{
|
||||
struct kfreecess_msg_data* payload = (struct kfreecess_msg_data*)data;
|
||||
|
||||
switch (payload->pkg_info.cmd) {
|
||||
case ADD_UID:
|
||||
freecess_add_uid(payload->pkg_info.uid);
|
||||
break;
|
||||
case DEL_UID:
|
||||
freecess_del_uid(payload->pkg_info.uid);
|
||||
break;
|
||||
case CLEAR_ALL_UID:
|
||||
freecess_clear_all();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void kfreecess_cfb_hook(void* data, unsigned int len)
|
||||
{
|
||||
struct kfreecess_msg_data* payload = (struct kfreecess_msg_data*)data;
|
||||
int uid = payload->target_uid;
|
||||
|
||||
printk(KERN_INFO "cfb_target: uid = %d\n", uid);
|
||||
binders_in_transcation(uid);
|
||||
}
|
||||
|
||||
static uid_t __sock_i_uid(struct sock *sk)
|
||||
{
|
||||
uid_t uid;
|
||||
|
||||
if(sk && sk->sk_socket) {
|
||||
uid = SOCK_INODE(sk->sk_socket)->i_uid.val;
|
||||
return uid;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int freecess_ip4_in(void *priv,
|
||||
struct sk_buff *skb,
|
||||
const struct nf_hook_state *state)
|
||||
{
|
||||
struct sock *sk;
|
||||
uid_t uid;
|
||||
int found;
|
||||
int protocol;
|
||||
|
||||
protocol = ip_hdr(skb)->protocol;
|
||||
if (protocol != IPPROTO_TCP)
|
||||
return NF_ACCEPT;
|
||||
|
||||
sk = skb_to_full_sk(skb);
|
||||
if (sk == NULL || !sk_fullsock(sk))
|
||||
return NF_ACCEPT;
|
||||
|
||||
uid = __sock_i_uid(sk);
|
||||
if (uid < UID_MIN_VALUE)
|
||||
return NF_ACCEPT;
|
||||
|
||||
found = find_and_clear_uid(uid);
|
||||
if (!found)
|
||||
return NF_ACCEPT;
|
||||
else if (pkg_report((int)uid) < 0)
|
||||
pr_err("%s : up report failed!\n", __func__);
|
||||
|
||||
return NF_ACCEPT;
|
||||
}
|
||||
|
||||
static unsigned int freecess_ip6_in(void *priv,
|
||||
struct sk_buff *skb,
|
||||
const struct nf_hook_state *state)
|
||||
{
|
||||
struct sock *sk;
|
||||
unsigned int thoff = 0;
|
||||
unsigned short frag_off = 0;
|
||||
int protohdr;
|
||||
uid_t uid;
|
||||
int found;
|
||||
|
||||
protohdr = ipv6_find_hdr(skb, &thoff, -1, &frag_off, NULL);
|
||||
if (protohdr != IPPROTO_TCP)
|
||||
return NF_ACCEPT;
|
||||
|
||||
sk = skb_to_full_sk(skb);
|
||||
if (sk == NULL || !sk_fullsock(sk))
|
||||
return NF_ACCEPT;
|
||||
|
||||
uid = __sock_i_uid(sk);
|
||||
if (uid < UID_MIN_VALUE)
|
||||
return NF_ACCEPT;
|
||||
|
||||
found = find_and_clear_uid(uid);
|
||||
if (!found)
|
||||
return NF_ACCEPT;
|
||||
else if (pkg_report((int)uid) < 0)
|
||||
pr_err("%s : up report failed!\n", __func__);
|
||||
|
||||
return NF_ACCEPT;
|
||||
}
|
||||
|
||||
static inline unsigned int freecess_ip4_out(void *priv,
|
||||
struct sk_buff *skb,
|
||||
const struct nf_hook_state *state)
|
||||
{
|
||||
return NF_ACCEPT;
|
||||
}
|
||||
|
||||
static inline unsigned int freecess_ip6_out(void *priv,
|
||||
struct sk_buff *skb,
|
||||
const struct nf_hook_state *state)
|
||||
{
|
||||
return NF_ACCEPT;
|
||||
}
|
||||
|
||||
static struct nf_hook_ops freecess_nf_ops[] = {
|
||||
|
||||
{
|
||||
.hook = freecess_ip4_in,
|
||||
.pf = NFPROTO_IPV4,
|
||||
.hooknum = NF_INET_LOCAL_IN,
|
||||
.priority = NF_IP_PRI_SELINUX_LAST + 1,
|
||||
},
|
||||
{
|
||||
.hook = freecess_ip6_in,
|
||||
.pf = NFPROTO_IPV6,
|
||||
.hooknum = NF_INET_LOCAL_IN,
|
||||
.priority = NF_IP6_PRI_SELINUX_LAST + 1,
|
||||
},
|
||||
|
||||
{
|
||||
.hook = freecess_ip4_out,
|
||||
.pf = NFPROTO_IPV4,
|
||||
.hooknum = NF_INET_LOCAL_OUT,
|
||||
.priority = NF_IP_PRI_SELINUX_LAST + 1,
|
||||
},
|
||||
{
|
||||
.hook = freecess_ip6_out,
|
||||
.pf = NFPROTO_IPV6,
|
||||
.hooknum = NF_INET_LOCAL_OUT,
|
||||
.priority = NF_IP6_PRI_SELINUX_LAST + 1,
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
static int __init kfreecess_pkg_init(void)
|
||||
{
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_REC_UID; i++)
|
||||
atomic_set(&uid_rec[i], 0);
|
||||
|
||||
ret = nf_register_hooks(freecess_nf_ops, ARRAY_SIZE(freecess_nf_ops));
|
||||
if (ret < 0) {
|
||||
pr_err("nf_register_hooks(freecess hooks) error\n");
|
||||
return -1;
|
||||
}
|
||||
pr_err("nf_register_hooks(freecess hooks) success\n");
|
||||
|
||||
register_kfreecess_hook(MOD_PKG, kfreecess_pkg_hook);
|
||||
register_kfreecess_hook(MOD_CFB, kfreecess_cfb_hook);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit kfreecess_pkg_exit(void)
|
||||
{
|
||||
unregister_kfreecess_hook(MOD_PKG);
|
||||
unregister_kfreecess_hook(MOD_CFB);
|
||||
|
||||
nf_unregister_hooks(freecess_nf_ops, ARRAY_SIZE(freecess_nf_ops));
|
||||
}
|
||||
|
||||
|
||||
module_init(kfreecess_pkg_init);
|
||||
module_exit(kfreecess_pkg_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
|
@ -450,40 +450,6 @@ static u64 freezer_parent_freezing_read(struct cgroup_subsys_state *css,
|
|||
return (bool)(freezer->state & CGROUP_FREEZING_PARENT);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SAMSUNG_FREECESS
|
||||
/**
|
||||
* Check if the task is allowed to be added to the freezer group
|
||||
* only the admin can add the task to the freezer group.
|
||||
*/
|
||||
static int freezer_can_attach(struct cgroup_taskset *tset)
|
||||
{
|
||||
const struct cred *cred = current_cred(), *tcred;
|
||||
struct task_struct *task;
|
||||
struct cgroup_subsys_state *css;
|
||||
|
||||
cgroup_taskset_for_each(task, css, tset) {
|
||||
tcred = __task_cred(task);
|
||||
|
||||
//Only system process and root have the permission.
|
||||
if ((current != task) && !(cred->euid.val == 1000 || capable(CAP_SYS_ADMIN))) {
|
||||
pr_err("Permission problem\n");
|
||||
return -EACCES;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel the attach action when it failed. It's usually used to restore the attach action.
|
||||
* But freezer attach just sends the signal, it will always success.
|
||||
* So, it doesn't need to restore any action.
|
||||
*/
|
||||
static void freezer_cancel_attach(struct cgroup_taskset *tset)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct cftype files[] = {
|
||||
{
|
||||
.name = "state",
|
||||
|
@ -512,8 +478,4 @@ struct cgroup_subsys freezer_cgrp_subsys = {
|
|||
.attach = freezer_attach,
|
||||
.fork = freezer_fork,
|
||||
.legacy_cftypes = files,
|
||||
#ifdef CONFIG_SAMSUNG_FREECESS
|
||||
.can_attach = freezer_can_attach,
|
||||
.cancel_attach = freezer_cancel_attach,
|
||||
#endif
|
||||
};
|
||||
|
|
|
@ -46,9 +46,6 @@
|
|||
#include <asm/siginfo.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include "audit.h" /* audit_signal_info() */
|
||||
#ifdef CONFIG_SAMSUNG_FREECESS
|
||||
#include <linux/freecess.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* SLAB caches for signal bits.
|
||||
|
@ -1208,12 +1205,6 @@ int do_send_sig_info(int sig, struct siginfo *info, struct task_struct *p,
|
|||
unsigned long flags;
|
||||
int ret = -ESRCH;
|
||||
|
||||
#ifdef CONFIG_SAMSUNG_FREECESS
|
||||
if ((sig == SIGKILL || sig == SIGTERM || sig == SIGABRT || sig == SIGQUIT))
|
||||
sig_report(current, p);
|
||||
|
||||
#endif
|
||||
|
||||
if (lock_task_sighand(p, &flags)) {
|
||||
ret = send_signal(sig, info, p, group);
|
||||
unlock_task_sighand(p, &flags);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue