You are on page 1of 10

Nombre: Uriel Masaki Gonzlez Arias.

Grupo: S8
Fecha: 01/10/15
Proyecto: Bomba Fork e Hilos (Thread)

Bomba FORK.
Una bomba fork es un ataque de tipo DoS para sistemas operativos.
Se le ha nombrado as por la funcin fork() de UNIX, encargada de crear
procesos hijos y base de este ataque.
Mediante unas pocas lneas de cdigo ejecutadas por cualquier usuario
de manera local, se puede tumbar cualquier mquina en cuestin de
segundos.
No es algo que se pueda parchear fcilmente debido a que no es ningn
fallo ni ninguna vulnerabilidad. Tampoco se puede identificar como virus
o malware, porque tampoco lo es. Una bomba fork suele hacer uso de
algo tan sencillo como un bucle infinito dentro del cual se crea un
proceso hijo.
De esta manera, el nmero de procesos en el sistema crece de forma
incontrolada hasta consumir los recursos de la mquina (memoria RAM y
procesador), quedando colgada.
El resultado?
Pues que hay que reiniciar a las bravas (lase tirando del cable o
pulsando el botn), pero nada ms. No supone ningn peligro, salvo que
estemos trabajando con algn documento y no hayamos guardado.
En resumidas cuentas, la bomba fork no es un agujero en la seguridad
de los sistemas operativos porque no produce ningn dao, porque lo
tiene que ejecutar el propio usuario del sistema y porque es ms bien
una caracterstica de los lenguajes de programacin y el resultado de un
programador oscioso. Vamos, que es lo mismo que tirar del cable de
alimentacin queriendo. Aun as, no deja de ser una bonita curiosidad.

Vamos a ver unos ejemplos. Empecemos con Linux. Existe una bomba
fork para este sistema que tiene el honor de ser considerada la bomba
ms bonita jams creada, tanto por su simplicidad como por su
elegancia. El cdigo es el siguiente:

:() { : | : & };:


As de simple. Si introducimos lo anterior en una consola de Linux,
probablemente el ordenador quedar inmediatamente colgado. O no.
Este cdigo se conoce desde hace bastante tiempo y es posible que en
vuestra distribucin de Linux ya no funcione porque hayan
implementado algn tipo de proteccin contra usuarios suicidas.
Si lo analizamos, es lo mismo que escribir lo siguiente:

funcion() {
funcion | funcion &
};
funcion
forkbomb Ahora est mucho ms claro: definimos una funcin y luego la
llamamos. Dentro de la misma, se llama a s misma y el resultado se
pasa por una tubera a ella misma de nuevo y todo estos se ejecuta en
segundo plano (carcter &). Es decir, de cada proceso salen dos
nuevos, y de cada uno de ellos, otros dos, y as hasta que el sistema
operativo lo permita.

Hilos (Threads)
Los threads son un concepto fundamental en lo que se conoce como
"programacin concurrente".
Un proceso es el resultado de una tcnica que emplean los sistemas
operativos para permitir la ejecucin simultnea de distintas
aplicaciones. Esta tcnica consiste en dejar correr a una aplicacin por
un tiempo, digamos 10 ms. Cuando se agota el tiempo, el kernel del SO
retoma el control y se lo entrega a otra aplicacin. Al mismo tiempo que
el SO cambia el control de una aplicacin a otra, tambin intercambia,
por cada aplicacin, informacin adicional tal como:
Qu archivos estn abiertos.
La memoria de la aplicacin.

La pila de ejecucin.

O sea, al salto se le suma el intercambio de informacin de contexto. Y a


la unidad compuesta por toda esa informacin contextual se la conoce
como proceso.
El concepto de thread implica solamente saltar, pero mantener el
contexto. Es decir que distintas partes de la aplicacin se ejecutan
concurrentemente, compartiendo memoria y archivos abiertos (la pila de
ejecucin no se intercambia).
Cuando Linux comenzaba, no tena threads. Los dems sistemas
operativos se pavoneaban exponiendo complejos mecanismos de
threads. En estos sistemas (como tambin es hoy en Windows), los
threads son conceptos de primer nivel en el sistema. Es decir que estn
implementados como algo especial y fijo.

Mientras tanto Linux creca y creca, pero solamente tena procesos. Las
primeras versiones de Java tenan que, en Linux, simular la existencia de
los threads. Linus Torvalds, el creador de Linux, siempre pens que los
threads eran algo muy parecido a los procesos, tan parecidos que deban
ser lo mismo. Mientras que un proceso nace de un fork "completo", los
threads vendran a ser el resultado de un fork parcial, en el que en vez
de duplicar todo el contexto, el proceso hijo mantenga parte de l
compartido con el padre. Entonces se cre una llamada al sistema que
permite decirla al sistema cules partes del contexto se desean duplicar,
esta llamada es clone().
Sin embargo, la forma estndar de manipular threads en UNIX (conocida
como pthreads) no era del todo compatible con esta conceptualizacin.
Por ejemplo espera que cada thread vea el mismo "identificadoe de
proceso", y con el mecanismo de Linux eso no era posible, ya que cada
thread era un proceso distinto.
A travs de los aos Linux fue aadiendo funciones para dar mejor
soporte a una API pthreads. La implementacin actual de pthreads
(conocida como NPTL) lleg actualmente a ofrecer el manejo exacto que
ofrecen otros sistemas.
Cmo se usan: La API (pthreads)
Veamos cmo es esa API...

La funcin principal es obviamente la que permite crear un thread. Esta


funcin es pthread_create:

int pthread_create(pthread_t * thread


, pthread_attr_t * attr
, void *(*funcion)(void *)
, void *arg);

Los parmetros son los siguientes:

thread
Un puntero en donde la funcin guardar el identificador del nuevo
thread creado.
attr
Atributos del thread, puede ser NULL.
funcion
Ac empieza la ejecucin del nuevo thread. Es un puntero a una
funcin declarada de esta manera: void mi_thread(void *arg);.
arg
Parmetro a pasar a la funcin del nuevo thread

Esta funcin devuelve el control inmediatamente... mientras tanto, el


nuevo thread inicia su recorrido por la funcin apuntada por funcion.
Hasta cundo? Como mucho hasta que termina ese mtodo, cuando
sale, termina el thread. Si un thread necesita esperar a que otro termina
(por ejemplo el thread padre esperar a que termine el hijo) puede usar la
funcin pthread_join(). Por qu se llama as? Bueno, crear un proceso es
como una bifuracin, se abren dos caminos... que uno espere a otro es lo
contrario, una unificacin (join en ingls).
La cuestin cuando se trabaja con threads es que la ejecucin avanza en
varias partes del programa a la vez. Cada una de esas ejecuciones
simultneas pueden tocar los mismos objetos. Eso a veces es un
problema. Un ejemplo: Suponga que un thread encola pedidos e

incrementa un contador. Existen adems 50 threads que se fijan si el


contador es mayor que cero y si lo es retiran un pedido, decrementan el
contador, y procesan la tarea. Supongamos que hay un pedido en la
cola, el contador vale 1, y que sucede lo siguiente:

El thread A comprueba que el contador vale ms que cero.


El thread B comprueba que el contador vale ms que cero.
Basado en su comprobacin el thread B decrementa el contador y
toma el pedido.
Basado en su comprobacin el thread A decrementa el contador y
toma el ped... auch, ya no hay pedido!

Qu pas ac?
El thread A mir, vio algo y se dispuso a actuar, pero cuando actu
alguien se le haba metido en el medio. El mundo ya no era el que era
cuando l tom la decisin de actuar. El problema, generalizado, es el
espacio de tiempo que hay entre mirar y actuar, cuando el mundo en el
que se mira es compartido por ms de un actor. A este tipo de
problemas se les llama condicin de carrera (en ingls race condition),
porque son como una competencia.
La solucin del problema
Para evitar el caso que expuse lo que se hace es establecer un lock, un
bloqueo. La API de threads provee algunos conceptos para hacer esto.
Uno de esos conceptos es el mutex. Un slo thread puede tomar el
mutex por vez, Si otro thread intenta tomar el mismo mutex, el segundo
thread se bloquea hasta que el primero suelte ese mutex.

Entonces, el ejemplo anterior modificado por la sabidura de los


bloqueos quedara as:

El thread A intenta tomar el mutex correspondiente a la cola. Lo


consigue: es suyo.
El thread A comprueba que el contador vale ms que cero.
El thread B intenta tomar el mutex correspondiente a la cola. No lo
consigue: lo tiene A, inicia espera.

Basado en su comprobacin el thread A decrementa el contador y


toma el pedido.
El thread A libera el mutex.
Al quedar el mutex liberado el thread B contina. Ahora tiene el
mutex.
El thread B comprueba que el contador vale cero.
Basado en su comprobacin el thread B ve que no tiene nada que
hacer.
El thread B libera el mutex.

/* Creamos MAX_THREAD threads que sacan por pantalla una cadena y


su
identificador
Una vez terminan su ejecucin devuelven como resultado su
identificador */
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_THREADS 10
// tabla con los identificadores de los threads
pthread_t tabla_thr[MAX_THREADS];
// tipo de datos y tabla con los parametros
typedef struct {
int id;
char *cadena;
} thr_param_t;
thr_param_t param[MAX_THREADS];
// tenemos que crear una tabla para los parmetros porque los pasamos
por
// referencia. As, si solo tuviramos una variable para los
parmetros
// al modificar esta modificaramos todas las que habamos pasado
anteriormente
// porque los threads no se quedan con el valor sino con la direccin
void *funcion_thr(thr_param_t *p)
{
// Esta es la funcion que ejecutan los threads
// como veras, no tiene mucho secreto...

printf("%s %d\n", p->cadena, p->id);


// una vez terminamos, devolvemos el valor
pthread_exit(&(p->id));
}
int main(void)
{
int i, *res;
// creamos los threads
printf("Creando threads...\n");
for (i=0; i<MAX_THREADS; i++) {
param[i].cadena = strdup("Hola, soy el thread");
param[i].id = i;
pthread_create(&tabla_thr[i], NULL, (void *)&funcion_thr,
(void *)&param[i]);
}
// esperamos que terminen los threads
printf("Threads creados. Esperando que terminen...\n");
for (i=0; i<MAX_THREADS; i++) {
pthread_join(tabla_thr[i], (void *)&res);
printf("El thread %d devolvio el valor %d\n", i, *res);
}
// sacamos el mensajito y salimos del programa
printf("Todos los threads finalizados. Adios!\n");
return 0;
}

using System;
using System.Threading;
public class Worker

{
// This method will be called when the thread is started.
public void DoWork()
{
while (!_shouldStop)
{
Console.WriteLine("worker thread: working...");
}
Console.WriteLine("worker thread: terminating gracefully.");
}
public void RequestStop()
{
_shouldStop = true;
}
// Volatile is used as hint to the compiler that this data
// member will be accessed by multiple threads.
private volatile bool _shouldStop;
}
public class WorkerThreadExample
{
static void Main()
{
// Create the thread object. This does not start the thread.
Worker workerObject = new Worker();
Thread workerThread = new Thread(workerObject.DoWork);
// Start the worker thread.
workerThread.Start();
Console.WriteLine("main thread: Starting worker thread...");
// Loop until worker thread activates.
while (!workerThread.IsAlive);
// Put the main thread to sleep for 1 millisecond to
// allow the worker thread to do some work:
Thread.Sleep(1);
// Request that the worker thread stop itself:
workerObject.RequestStop();
// Use the Join method to block the current thread
// until the object's thread terminates.
workerThread.Join();
Console.WriteLine("main thread: Worker thread has terminated.");
}

You might also like