Saludos a todos, después de una larga jornada de ausencia hoy les traigo un driver que programé
para linux, la cual consta de 3 partes:
2 drivers(1 en modo ring0 y el otro en el de espacio de usuario).
la 3º parte es la interfaz grafica, que, además de presentar una GUI es la encargada de comunicarse
con el driver de usuario y este a la vez se comunica con el driver que interactúa con el kernel.

Logre entender y desarrollar un mecanismo por medio de netlink sockets optimizados(en vez de usar pipes)
que se comunican entre si (kernel y usuario), y así hay una retroalimentacion en la información de ambos,
claro que esto es una beta y que MUCHO por optimizar/agregar/mejorar la GUI esta hecha en Pascal, mientras
que los drivers en C, y la GUI se "comunica" con C gracias a librerias compartidas (.o y .ko).

Éste código esta hecho 100% por mi, no hay rips, ni nada por el estilo...
Por esto le pido a los ripers que tengan consideración y respeto por el esfuerzo
y que si van a tomar este código por lo menos den creditos...


Este sistema se compone de algunas de las siguientes características :
[+]Matar procesos en ring0
[+]congelar procesos.
[+]refrigerar procesos, que han sido congelado o bien estan congelados(no funciona con todos).
[+]poner toda esa info en colas(Queues) para tener un registro.
[+]Informacion de procesos, consumo virtual, Shared memory, RSS, Boot time, flags, y muchos mas.
[+]Debugear el kernel (para ver los logs del kernel)
[+]Listar procesos por alto consumo virtual
[+]Configurar el driver, para que si un determinado proceso alcanze un consumo alto de memoria ocurra
un determinado evento.

Espero tener más tiempo y seguir mejorando cosas y demás, debo decir que esta aplicacion contiene algunos
bugs que espero solucionar... por esto la lanzo como beta y POR FAVOR les pido que la TESTEN y COMENTEN
que costo muchas horas de desarrollo y asumir conceptos.

Aca les dejos el link de la aplicacion: [Enlace externo eliminado para invitados]

a continuación dejaré parte del código(por lo menos el del driver principal) y algunas imagenes.
Mañana en la seccion C lo pongo completo, como respaldo por las dudas...
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/netlink.h>
#include <net/sock.h>
#include <net/net_namespace.h>

/* si quires debuggear descomenta esta de lo contrario comentala */
#define DEBUG_ANTIFREEZE_DRIVER

/* Necesaria para interactuar con el espacio de usuario y kernel */
#define NETLINK_KERNEL_GROUP 		30

#define REFRIGERATE_PROCESS 		18
#define FREEZE_PROCESS			19
#define KILL_PROCESS			15

#define _KILL_PROCESS			"[KILL_SIGNAL]"
#define _FREEZE_PROCESS			"[FREEZE_SIGNAL]"
#define _REFRIGERATE_PROCESS		"[REFRIGERATE_SIGNAL]"
#define PID_EX				"[PID_EX]"

#define EZOMBIE 			"EXIT_ZOMBIE|"
#define EDEAD				"EXIT_DEAD|"
#define TDEAD				"TASK_DEAD|"
#define TKILL				"TASK_KILLABLE|"
#define TTRACED				"TASK_TRACED|"
#define TSTOP				"TASK_STOPPED|"
#define TWAKEKILL			"TASK_WAKEKILL|"
#define TWAKING				"TASK_WAKING|"
#define TINTRPT				"TASK_INTERRUPTIBLE|"
#define TUNINTERPT			"TASK_UNINTERRUPTIBLE|"
#define TRUNN				"TASK_RUNNING|"
#define TMAX				"TASK_STATE_MAX|"

MODULE_LICENSE("GPL");
MODULE_AUTHOR("NvK");
MODULE_DESCRIPTION("Modulo para controlar y obtener el consumo de procesos, pudiendolos optimizar y evitar posibles latencias");

static struct sock *nl_sk= NULL;
static struct task_struct *ktask;
static struct mm_struct *MMU;
static struct vm_area_struct *VMA;
static struct pid *pid_struct;

struct nlmsghdr *nlh= NULL;
struct sk_buff *sk_ob;

/* con un ushort basta y sobra (congela/descongela/mata un proceso en modo ring0) */
static uint8_t frozen_process_r0(__u32 _pid,
				 struct pid *pid_struct, 
				 struct task_struct *_ktask, 
				 __u8 _signal)
{
  atomic_t pid_status;
  pid_struct= task_pid(_ktask);
  if (((*_ktask).pid==_pid)&&(pid_struct!=NULL)){
    _ktask->state= TASK_INTERRUPTIBLE;
    kill_pid(pid_struct, _signal, TASK_INTERRUPTIBLE); //kill_pid(pid_struct, SIGSTOP, TASK_INTERRUPTIBLE);
    atomic_set(&pid_status, SIGHUP);
  }else
  { 
    atomic_set(&pid_status, SIGABRT);
  }
  
  return atomic_read(&pid_status);
}

static uint8_t __attribute__((__section__(".text.init") ))
 nl_KernelSend(char *Message, int nl_pid)
{
  /* Necesario para enviar un mensaje */
  sk_ob= nlmsg_new(strlen(Message), 0);
  nlh= nlmsg_put(sk_ob, 0, 0, NLMSG_DONE, strlen(Message), 0); // escribo la estructura
  NETLINK_CB(sk_ob).dst_group= 0;
  strncpy(NLMSG_DATA(nlh), Message , strlen(Message));
  nlmsg_unicast(nl_sk, sk_ob, nl_pid);
  
  return 1;
}

/* Convierto la cadena de texto en integro */
static int32_t __attribute__((__section__(".text.init") ))
 strcpysignal(char nl_buf[], char *type_signal)
{
  int base_int;
  char signal[1040];
  
  strncpy(signal, nl_buf+strlen(type_signal), strlen(nl_buf)-1);
  return simple_strtol((const char *)signal, NULL, base_int);
}

// sysctl -w vm.drop_caches=3
static void __attribute__((__section__(".text.init") ))
 netlink_recv(struct sk_buff *skb)
{
  int pid, pid_signal, type_signal;
  char *sbuff;
  char nl_buf[1024];
  unsigned long get_mm, hiwater_vm,
    total_vm, hiwater_rss, total_rss,
    swap, size_kb;
  
  if (skb!=NULL)
  {
    // Reservo el tamaño de una pagina de memoria
    sbuff= (char *)vmalloc(sizeof(char)*PAGE_SIZE + 1);
    memset(sbuff, 0x0000, sizeof(sbuff));
    memset(nl_buf, 0x0000, sizeof(nl_buf));
    
    nlh= (struct nlmsghdr *)skb->data;
    sprintf(nl_buf, "%s", (char *)NLMSG_DATA(nlh));
#ifdef DEBUG_ANTIFREEZE_DRIVER
    printk(KERN_INFO "<SEÑAL> %s\n", nl_buf);
#endif
    
    pid_signal= -1;
    if (strstr(nl_buf, _KILL_PROCESS)!=NULL)
    {
      pid_signal= strcpysignal(nl_buf, _KILL_PROCESS);
#ifdef DEBUG_ANTIFREEZE_DRIVER
      printk(KERN_INFO "\n<PID_SIGNAL> %d (KILL_PROCESS)\n", pid_signal);
#endif
      type_signal= KILL_PROCESS;
    }
    if (strstr(nl_buf, _FREEZE_PROCESS)!=NULL)
    {
      pid_signal= strcpysignal(nl_buf, _FREEZE_PROCESS);
#ifdef DEBUG_ANTIFREEZE_DRIVER
      printk(KERN_INFO "\n<PID_SIGNAL> %d (FREEZE_PROCESS)\n", pid_signal);
#endif
      type_signal= FREEZE_PROCESS;
    }
    if (strstr(nl_buf, _REFRIGERATE_PROCESS)!=NULL)
    {
      pid_signal= strcpysignal(nl_buf, _REFRIGERATE_PROCESS);
#ifdef DEBUG_ANTIFREEZE_DRIVER
      printk(KERN_INFO "\n<PID_SIGNAL> %d (REFRIGERATE_PROCESS)\n", pid_signal);
#endif
      type_signal= REFRIGERATE_PROCESS;
    }
    
    pid= nlh->nlmsg_pid;
    printk(KERN_INFO "----------------------------------------------");
    for(ktask= &init_task; (ktask= next_task(ktask))!=&init_task;)
    {
      memset(sbuff, 0x0000, sizeof(sbuff));
      
      if (pid_signal!=-1)
	frozen_process_r0((int)pid_signal, pid_struct, ktask, type_signal);
      
      sprintf(sbuff, "(PAR)%s|",(char *)ktask->parent->comm); //(*pktask).utime
      sprintf(sbuff+strlen(sbuff), "(PID)%d|", (int *)ktask->pid);
      /*
      if (strstr(nl_buf, "[PID_EX]")!=NULL){
	if(ktask->pid==simple_strtol((const char *)strstr(nl_buf,PID_EX)+strlen(PID_EX), NULL, type_signal)){
	  printk("PID_EX RECIBIDO [%s]", strstr(nl_buf, PID_EX)+strlen(PID_EX));
	  sprintf(sbuff+strlen(sbuff), "[PID_EX]__%d__|", (int *)ktask->pid);
	}
      }*/
      
      MMU= ktask->mm;
      if (MMU!=0x0)
      {
	hiwater_vm = total_vm = MMU->total_vm;
	if (hiwater_vm < MMU->hiwater_vm)
	  hiwater_vm = MMU->hiwater_vm;
	hiwater_rss = total_rss = atomic_long_read(&MMU->rss_stat.count[MM_FILEPAGES]) + atomic_long_read(&MMU->rss_stat.count[MM_ANONPAGES]);
	if (hiwater_rss < MMU->hiwater_rss)
	  hiwater_rss = MMU->hiwater_rss;
	swap= atomic_long_read(&MMU->rss_stat.count[MM_SWAPENTS]);
	sprintf(sbuff+strlen(sbuff), "(VIRT)%lu|", (unsigned long *)(MMU->total_vm<<(PAGE_SHIFT-0x0A)));
	sprintf(sbuff+strlen(sbuff), "(RSS)%lu|", (unsigned long *)(total_rss << (PAGE_SHIFT - 0xA)));
	sprintf(sbuff+strlen(sbuff), "(ShrVM)%lu|", (unsigned long *)(MMU->shared_vm));
	sprintf(sbuff+strlen(sbuff), "(VMPeak)%lu|", (unsigned long *)(MMU->hiwater_vm<<(PAGE_SHIFT-0x0A)));
	sprintf(sbuff+strlen(sbuff), "(VMHWM)%lu|", (unsigned long *)(MMU->hiwater_rss<<(PAGE_SHIFT-0x0A)));
	sprintf(sbuff+strlen(sbuff), "(VmPTE)%lu|", (unsigned long *)(((PTRS_PER_PTE*sizeof(pte_t)*MMU->nr_ptes) >> 0xA)) );
	sprintf(sbuff+strlen(sbuff), "(VData)%lu|", (unsigned long *)((MMU->total_vm - MMU->shared_vm - MMU->stack_vm)<<(PAGE_SHIFT-0x0A)) );
	sprintf(sbuff+strlen(sbuff), "(VStack)%lu|", (unsigned long *)(MMU->stack_vm<<(PAGE_SHIFT-0x0A)) );
	sprintf(sbuff+strlen(sbuff), "(VmSwap)%lu|", (unsigned long *)(swap << (PAGE_SHIFT - 0xa)) );
	sprintf(sbuff+strlen(sbuff), "(VmPin)%lu|", (unsigned long *)(MMU->pinned_vm << (PAGE_SHIFT-0xA)));
	sprintf(sbuff+strlen(sbuff), "(VmLib)%lu|", (unsigned long *)( ((MMU->exec_vm << (PAGE_SHIFT-0xA)) - (PAGE_ALIGN(MMU->end_code) - (MMU->start_code & PAGE_MASK)) >> 0xA)) );
	VMA= MMU->mmap;
	if (VMA!=0x0){
	  size_kb= (VMA->vm_end - VMA->vm_start)>>0x0A;
	  sprintf(sbuff+strlen(sbuff), "(Sz)%lu|", (unsigned long *)size_kb);
	}
      }
      
      switch((*ktask).state) {
	case EXIT_ZOMBIE: sprintf(sbuff+strlen(sbuff), "(FLAG)%s", EZOMBIE); break;
	case EXIT_DEAD: sprintf(sbuff+strlen(sbuff), "(FLAG)%s", EDEAD); break;
	case TASK_DEAD: sprintf(sbuff+strlen(sbuff), "(FLAG)%s", TDEAD); break;
	case TASK_KILLABLE: sprintf(sbuff+strlen(sbuff), "(FLAG)%s", TKILL); break;
	case TASK_STOPPED: sprintf(sbuff+strlen(sbuff), "(FLAG)%s", TSTOP);	break;
	case TASK_WAKEKILL: sprintf(sbuff+strlen(sbuff), "(FLAG)%s", TWAKEKILL); break;
	case TASK_WAKING: sprintf(sbuff+strlen(sbuff), "(FLAG)%s", TWAKING);	break;
	case TASK_INTERRUPTIBLE: sprintf(sbuff+strlen(sbuff), "(FLAG)%s", TINTRPT);	break;
	case TASK_UNINTERRUPTIBLE: sprintf(sbuff+strlen(sbuff), "(FLAG)%s", TUNINTERPT); break;
	case TASK_RUNNING: sprintf(sbuff+strlen(sbuff), "(FLAG)%s", TRUNN);	break;
	case TASK_STATE_MAX : sprintf(sbuff+strlen(sbuff), "(FLAG)%s", TMAX);	break;
	case TASK_TRACED : sprintf(sbuff+strlen(sbuff), "(FLAG)%s", TTRACED);	break;
      }
	if (ktask->prio>=0 && ktask->prio<=99)
	  sprintf(sbuff+strlen(sbuff), "(PRIO)REALTIME|");
	if (ktask->prio>=100)
	  sprintf(sbuff+strlen(sbuff), "(PRIO)NORMAL|");
	//printk(KERN_INFO "priority:  %d ", (int *)ktask->prio);
	//printk(KERN_INFO "policy: %lu ", (unsigned long *)ktask->policy);
	if (ktask->policy==0)
	  sprintf(sbuff+strlen(sbuff), "(PLY)SCHED_OTHER|");
	if (ktask->policy==1)
	  sprintf(sbuff+strlen(sbuff), "(PLY)SCHED_FIFO|");
	if (ktask->policy==2)
	  sprintf(sbuff+strlen(sbuff), "(PLY)SCHED_RR|");
	sprintf(sbuff+strlen(sbuff), "(UT)%lu|", (unsigned long *)ktask->utime);
	sprintf(sbuff+strlen(sbuff), "(ST)%lu|", (unsigned long *)ktask->stime);
	sprintf(sbuff+strlen(sbuff), "(BT)%i64|", ktask->real_start_time);
	nl_KernelSend(sbuff, pid);
	
    }
    
    nl_KernelSend("KERN_TC", pid);
    if(sbuff) vfree(sbuff);
  }
}

static int __section(.init.text) __cold notrace
 __INIT_KERNEL(void)
{
  printk(KERN_ALERT "Driver inicializado correctamente (esperando señal).");
  nl_sk= netlink_kernel_create((struct net *)&(init_net),
			       NETLINK_KERNEL_GROUP,
			       0,
			       netlink_recv,
			       NULL,
			       THIS_MODULE);
  return 0;
}

static void __section(.exit.data)
 __EXIT_KERNEL(void)
{
  //free_task((struct task_struct *)ktask);
  sock_release(nl_sk->sk_socket);
}

module_init(__INIT_KERNEL);
module_exit(__EXIT_KERNEL);
Imagen


Imagen


Imagen


Imagen


Imagen


Imagen


Saludos NvK.
Responder

Volver a “Nuestros Programas”