+ All Categories
Home > Documents > 1 Lección 9: EXEC Tinguaro Tadeo del Rosario Juan José Muñoz García.

1 Lección 9: EXEC Tinguaro Tadeo del Rosario Juan José Muñoz García.

Date post: 23-Jan-2016
Category:
Upload: raymundo-muniz
View: 225 times
Download: 0 times
Share this document with a friend
35
1 Lección 9: EXEC Tinguaro Tadeo del Rosario Juan José Muñoz García
Transcript
Page 1: 1 Lección 9: EXEC Tinguaro Tadeo del Rosario Juan José Muñoz García.

1

Lección 9: EXEC

Tinguaro Tadeo del RosarioJuan José Muñoz García

Page 2: 1 Lección 9: EXEC Tinguaro Tadeo del Rosario Juan José Muñoz García.

2

Introducción

Un fork crea un proceso hijo que ejecuta el mismo programa, mientras que con un exec se puede lanzar a ejecutar un nuevo programa. El exec permite crear un proceso que ejecuta un código distinto al del padre.Si no existiera el fork y el exec, siempre estaría ejecutándose el proceso init, porque el resto serían simplemente hijos de él.

Page 3: 1 Lección 9: EXEC Tinguaro Tadeo del Rosario Juan José Muñoz García.

3

Familia de funciones

Realmente, no existe ninguna función llamada exec.Siempre estaremos haciendo referencia al conjunto de funciones que poseen la misma funcionalidad, pero que se diferencian en el modo en el que se les pasan los argumentos.La familia está formada por: execl, execle, execve, execlp, execvp y execv.

Page 4: 1 Lección 9: EXEC Tinguaro Tadeo del Rosario Juan José Muñoz García.

4

Modo de uso

En caso de éxito en un exec no hay retorno, porque el proceso que llama, ejecuta ahora un nuevo programa.Para crear nuevos procesos, generalmente se siguen dos pasos:– Se crea una copia del proceso padre mediante fork

o clone.– El hijo lanza a ejecutar, mediante exec el nuevo

programa.

Page 5: 1 Lección 9: EXEC Tinguaro Tadeo del Rosario Juan José Muñoz García.

5

Modo de uso

if (forkfork()){

// Esto lo ejecuta el padre}else{

// Esto lo ejecuta el hijoexeclexecl(“programa”, “programa”);// Finaliza el proceso hijo

}

Page 6: 1 Lección 9: EXEC Tinguaro Tadeo del Rosario Juan José Muñoz García.

6

Implementación del exec

El código fuente de la implementación del exec se encuentra en /fs/exec.c.

La función principal que lleva a cabo la implementación es do_execve.Otras funciones importantes son:– prepare_binprm: prepara los parámetros del fichero

ejecutable.– search_binary_handler: busca el manejador para el tipo de

ejecutable que se trate.

Page 7: 1 Lección 9: EXEC Tinguaro Tadeo del Rosario Juan José Muñoz García.

7

do_execve

La funcionalidad básica es la siguiente:– Lee de memoria información característica del ejecutable

(prepare_binprm): de los primeros 128 bytes.– Prepara el entorno y argumentos del nuevo programa.– Busca el manejador para el tipo de ejecutable que se

esté tratando (search_binary_handler).

Page 8: 1 Lección 9: EXEC Tinguaro Tadeo del Rosario Juan José Muñoz García.

8

Estructura utilizada para configurar parámetros de ejecución del proceso, antes de lanzarlo a ejecutar

do_execve - linux_binprmlinux_binprm

struct linux_binprm{ char buf[BINPRM_BUF_SIZE]; // Para leer los primeros 128 bytes struct page *page[MAX_ARG_PAGES]; // Tabla pagina del proceso unsigned long p; // Longitud de la memoria utilizada struct dentry * dentry; // Identificador de fichero del ejecutable int e_uid, e_gid; // uid y gid efectivos int argc, envc; // Numero de argumentos y variables de entorno char * filename; /* Nombre del ejecutable */};

Page 9: 1 Lección 9: EXEC Tinguaro Tadeo del Rosario Juan José Muñoz García.

9

Estructura utilizada para configurar parámetros de ejecución del proceso, antes de lanzarlo a ejecutar

do_execve - linux_binprmlinux_binprm

struct linux_binprm{ char buf[BINPRM_BUF_SIZE]; // Para leer los primeros 128 bytes struct page *page[MAX_ARG_PAGES]; // Tabla pagina del proceso unsigned long p; // Longitud de la memoria utilizada struct dentry * dentry; // Identificador de fichero del ejecutable int e_uid, e_gid; // uid y gid efectivos int argc, envc; // Numero de argumentos y variables de entorno char * filename; /* Nombre del ejecutable */};

•El UID real es el identificador del usuario que ha lanzado el proceso.•El EUID es el identificador que usa el sistema para los controles de acceso. Puede ser distinto al del usuario real (bit SETUID)•Si el fichero ejecutado tiene activo el bit SETUID, se cambia el e_uid del proceso que hizo la llamada al del propietario del fichero ejecutable.•Si no lo tiene activo, el e_uid será el del proceso que hizo la llamada.

Page 10: 1 Lección 9: EXEC Tinguaro Tadeo del Rosario Juan José Muñoz García.

10

do_execve - Tabla de páginasTabla de páginas

Número depágina

Tabla depágina

Marco enmemoria física

- Para reducir el tiempo de acceso a memoria física, se utilizantablas TLB- El registro PTBR apunta a la dirección en memoria principalque contiene la tabla de página

Page 11: 1 Lección 9: EXEC Tinguaro Tadeo del Rosario Juan José Muñoz García.

11

10079 int do_execve(char * filename, char ** argv,10080 char ** envp, struct pt_regs * regs)10081 {10082 struct linux_binprm bprm;10083 struct dentry * dentry;10084 int retval;10085 int i;10086 10087 bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);10088 for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear pg-tbl */10089 bprm.page[i] = 0;10090 10091 dentry = open_namei(filename, 0, 0);10092 retval = PTR_ERR(dentry);10093 if (IS_ERR(dentry))10094 return retval;

do_execve

Inicializamos tabla de páginas

Comprobamos existencia del ejecutable.Se podría hacer antes para optimizar

Page 12: 1 Lección 9: EXEC Tinguaro Tadeo del Rosario Juan José Muñoz García.

12

do_execve

10096 bprm.dentry = dentry;10097 bprm.filename = filename;10098 bprm.sh_bang = 0;10099 bprm.java = 0;10100 bprm.loader = 0;10101 bprm.exec = 0;10102 if ((bprm.argc = count(argv)) < 0) {10103 dput(dentry);10104 return bprm.argc;10105 }10106 10107 if ((bprm.envc = count(envp)) < 0) {10108 dput(dentry);10109 return bprm.envc;10110 }10111 10112 retval = prepare_binprm(&bprm);

Count cuenta el número de punterosno-nulos de los vectores argv y envp

que son los argumentos y lasvariables de entorno.

Page 13: 1 Lección 9: EXEC Tinguaro Tadeo del Rosario Juan José Muñoz García.

13

do_execve

10096 bprm.dentry = dentry;10097 bprm.filename = filename;10098 bprm.sh_bang = 0;10099 bprm.java = 0;10100 bprm.loader = 0;10101 bprm.exec = 0;10102 if ((bprm.argc = count(argv)) < 0) {10103 dput(dentry);10104 return bprm.argc;10105 }10106 10107 if ((bprm.envc = count(envp)) < 0) {10108 dput(dentry);10109 return bprm.envc;10110 }10111 10112 retval = prepare_binprm(&bprm);

Count cuenta el número de punterosno-nulos de los vectores argv y envp

que son los argumentos y lasvariables de entorno.•argv es un array de cadenas de argumentos pasados al nuevo programa.

•envp es un array de cadenas, que se pasan como entorno al nuevo programa.•Tanto argv como envp deben terminar en un puntero nulo.

Page 14: 1 Lección 9: EXEC Tinguaro Tadeo del Rosario Juan José Muñoz García.

14

do_execve

10114 if (retval >= 0) {10115 bprm.p = copy_strings(1, &bprm.filename, bprm.page,10116 bprm.p, 2);10117 bprm.exec = bprm.p;10118 bprm.p = copy_strings(bprm.envc,envp,bprm.page,10119 bprm.p,0);10120 bprm.p = copy_strings(bprm.argc,argv,bprm.page,10121 bprm.p,0);10122 if (!bprm.p)10123 retval = -E2BIG;10124 }10125 10126 if (retval >= 0)10127 retval = search_binary_handler(&bprm,regs);10128 if (retval >= 0)10129 /* execve success */10130 return retval;

Copia al espacio de memoria del proceso,el nombre del fichero, las variables deentorno y los argumentos.Si no queda memoria libre, error

Page 15: 1 Lección 9: EXEC Tinguaro Tadeo del Rosario Juan José Muñoz García.

15

do_execve

10132 /* Something went wrong, return the inode and free the10133 * argument pages*/10134 if (bprm.dentry)10135 dput(bprm.dentry);10136 10137 for (i=0 ; i<MAX_ARG_PAGES ; i++)10138 free_page(bprm.page[i]);10139 10140 return retval;10141 } Liberamos memoria del

proceso

Si algo va mal, devuelve el “inodo” y libera los argumentos de las páginas.

Page 16: 1 Lección 9: EXEC Tinguaro Tadeo del Rosario Juan José Muñoz García.

16

do_execve - countcount

9480 static int count(char ** argv)9481 {9482 int i = 0;9484 if (argv != NULL) {9485 for (;;) {9486 char * p;9487 int error;9488 9489 error = get_user(p,argv); 9490 if (error)9491 return error;9492 if (!p)9493 break;9494 argv++;9495 i++;9496 }9497 }9498 return i; 9499 }

Recoge los parámetros

Cuando encuentra un null sale

Devuelve el número de parámetros, que se le pasan a la función que lanza el exec

Page 17: 1 Lección 9: EXEC Tinguaro Tadeo del Rosario Juan José Muñoz García.

17

do_execve - prepare_binprmprepare_binprm

9832 int prepare_binprm(struct linux_binprm *bprm)9833 {9834 int mode;9835 int retval,id_change,cap_raised;9836 struct inode * inode = bprm->dentry->d_inode;9838 mode = inode->i_mode;9839 if (!S_ISREG(mode))9840 return -EACCES;9841 if (!(mode & 0111))9842 return -EACCES;9843 if (IS_NOEXEC(inode))9844 return -EACCES;9845 if (!inode->i_sb)9846 return -EACCES;9847 if ((retval = permission(inode, MAY_EXEC)) != 0)9848 return retval;9850 if (inode->i_writecount > 0)9851 return -ETXTBSY;

Comprueba que es un fichero regular ejecutable, que tiene permiso de ejecución y que no se está escribiendo

Page 18: 1 Lección 9: EXEC Tinguaro Tadeo del Rosario Juan José Muñoz García.

18

do_execve - prepare_binprmprepare_binprm

9853 bprm->e_uid = current->euid;9854 bprm->e_gid = current->egid;9855 id_change = cap_raised = 0;9856 9857 /* Set-uid? */9858 if (mode & S_ISUID) {9859 bprm->e_uid = inode->i_uid;9860 if (bprm->e_uid != current->euid)9861 id_change = 1;9862 }9863 /*Set-gid?*/9868 if ((mode & (S_ISGID | S_IXGRP)) ==9869 (S_ISGID | S_IXGRP)) {9870 bprm->e_gid = inode->i_gid;9871 if (!in_group_p(bprm->e_gid))9872 id_change = 1;9873 }

Si el setuid y/o setgid están activos, los nuevos procesos

se tratarán como usuarios / grupos diferentes

Page 19: 1 Lección 9: EXEC Tinguaro Tadeo del Rosario Juan José Muñoz García.

19

do_execve - prepare_binprmprepare_binprm

9933 return read_exec(bprm->dentry,0,bprm->buf,128,1);

Finalmente, leemos los primeros 128 bytes del fichero, y lo introducimos en la estructura bprm. Una posible optimización del kernel sería reemplazar 128 por

un define.

El buffer sirve para identificar el tipo de ejecutable que estamos tratando

Page 20: 1 Lección 9: EXEC Tinguaro Tadeo del Rosario Juan José Muñoz García.

20

do_execve - copy_stringcopy_string

9519 unsigned long copy_strings(9520 int argc,char ** argv,9521 unsigned long *page, unsigned long p, int from_kmem)9522 {9531 while (argc-- > 0) {9537 get_user(str, argv+argc);9542 len = strlen_user(str); 9549 while (len) {9553 offset = pos % PAGE_SIZE;9555 pag = (char *) page[pos/PAGE_SIZE] =9556 (unsigned long *) get_free_page(GFP_USER))9561 bytes_to_copy = PAGE_SIZE - offset;9564 copy_from_user(pag + offset, str, bytes_to_copy);9567 len -= bytes_to_copy;9568 }9569 }9572 return p;9573 }

Traemos los argumentos de la memoria deusuario, y calculamos la longitud

Page 21: 1 Lección 9: EXEC Tinguaro Tadeo del Rosario Juan José Muñoz García.

21

do_execve - copy_stringcopy_string

9519 unsigned long copy_strings(9520 int argc,char ** argv,9521 unsigned long *page, unsigned long p, int from_kmem)9522 {9531 while (argc-- > 0) {9537 get_user(str, argv+argc);9542 len = strlen_user(str); 9549 while (len) {9553 offset = pos % PAGE_SIZE;9555 pag = (char *) page[pos/PAGE_SIZE] =9556 (unsigned long *) get_free_page(GFP_USER))9561 bytes_to_copy = PAGE_SIZE - offset;9564 copy_from_user(pag + offset, str, bytes_to_copy);9567 len -= bytes_to_copy;9568 }9569 }9572 return p;9573 }

Traemos los argumentos de la memoria deusuario, y calculamos la longitud

Calculamos una entrada en la tabla de páginas,le asignamos una dirección de memoria física y

copiamos en la memoria física el argumento.(Copiamos de página en página)

Page 22: 1 Lección 9: EXEC Tinguaro Tadeo del Rosario Juan José Muñoz García.

22

MANEJADOR BINARIO:

Mecanismo del núcleo para tratar la variedad de formatos binarios de manera consistente.No todos los programas se almacenan en el mismo formato: un ejemplo “Java Handler”, “Scripts”.

do_execve - search_binary_handlersearch_binary_handler

9996 int search_binary_handler(struct linux_binprm *bprm,9997 struct pt_regs *regs)9998 {10036 for (try=0; try<2; try++) {10037 for (fmt = formats ; fmt ; fmt = fmt->next) {10038 int (*fn)(struct linux_binprm *, struct pt_regs *)10039 = fmt->load_binary;10040 if (!fn)10041 continue;10042 retval = fn(bprm, regs);10043 if (retval >= 0) {10044 if (bprm->dentry)10045 dput(bprm->dentry);10046 bprm->dentry = NULL;10047 current->did_exec = 1;10048 return retval;10049 }

Llamamos a load_binary hasta queretorne no-negativo. Para así poder utilizar

las funciones que tratan cada ejecutable.

Page 23: 1 Lección 9: EXEC Tinguaro Tadeo del Rosario Juan José Muñoz García.

23

do_execve - search_binary_handlersearch_binary_handler

10050 if (retval != -ENOEXEC)10051 break;10052 /* We don't have the dentry anymore */10053 if (!bprm->dentry)10054 return retval;10055 }10056 if (retval != -ENOEXEC) {10057 break;10059 } else {10068 sprintf(modname, "binfmt-%04x",10069 *(unsigned short *)(&bprm->buf[2]));10070 request_module(modname);10072 }10073 }10074 return retval;10075 }

Si no se encuentra ningún manejadorse hace un segundo intento, obteniendoprimero un código de formatonuevo, que indique el posible tipo de fichero binario

Page 24: 1 Lección 9: EXEC Tinguaro Tadeo del Rosario Juan José Muñoz García.

24

formatos ejecutables

No todos los programas están almacenados en el mismo formatoLinux usa manejadores binarios para abstraer las diferencias entre los distintos formatosPara cada formato se usa un manejador específicoELF es el formato nativo de ejecutables Linux

Page 25: 1 Lección 9: EXEC Tinguaro Tadeo del Rosario Juan José Muñoz García.

25

formatos ejecutables

ELF sustituye a otro formato llamado a.out, que es el que se utilizaba como nativo en versiones anteriores del kernelLos manejadores binarios reconocen cualquier número mágico que se encuentre al comienzo de un fichero

Page 26: 1 Lección 9: EXEC Tinguaro Tadeo del Rosario Juan José Muñoz García.

26

formatos ejecutables

También pueden realizar el reconocimiento del formato por alguna propiedad del nombrePor ejemplo, los binarios java se identifican por su extensión class o por su número mágico 0xCAFEBADE

Page 27: 1 Lección 9: EXEC Tinguaro Tadeo del Rosario Juan José Muñoz García.

27

formatos ejecutables

El kernel 2.2 soporta los siguientes manejadores:– a.out: antiguo formato nativo de linux. Está en

desuso, pero aún se le proporciona soporte– ELF: formato actual de los binarios Linux. A pesar

de ser el formato nativo, se incluye un manejador para homogeneizar el núcleo, y hacerlo más sencillo

Page 28: 1 Lección 9: EXEC Tinguaro Tadeo del Rosario Juan José Muñoz García.

28

formatos ejecutables

– EM86: empleado para ejecutar binarios Linux en máquinas con arquitectura Alpha

– Misc: el manejador de este formato puede reconocer gran variedad de formatos por extensión, o por número mágico. La gran ventaja que tiene, es que es configurable en tiempo de ejecución, no solo de compilación, y por lo tanto no es necesario recompilar el núcleo para dar soporte a un nuevo formato. En el futuro, los handlers de Java y EM86 serán de este tipo

Page 29: 1 Lección 9: EXEC Tinguaro Tadeo del Rosario Juan José Muñoz García.

29

formatos ejecutables

– Scripts: utilizado para ejecutar scripts del shell. Trata los ficheros cuyos 2 primeros caracteres sean #!

Page 30: 1 Lección 9: EXEC Tinguaro Tadeo del Rosario Juan José Muñoz García.

30

Un ejemplo: java handler

En fs/binfmt_java.c se encuentran las funciones encargadas de manejar los ficheros java, tanto ejecutables como applets

do_execve Search_binary_handler do_load_java

Page 31: 1 Lección 9: EXEC Tinguaro Tadeo del Rosario Juan José Muñoz García.

31

do_load_java: Hace todo lo necesario para la carga de ficheros .class de Java

java handler - do_load_javado_load_java

static int do_load_java(struct linux_binprm *bprm,struct pt_regs *regs){

unsigned char *ucp = (unsigned char *) bprm->buf;

if ((ucp[0] != 0xca) || (ucp[1] != 0xfe) || (ucp[2] != 0xba) || (ucp[3] != 0xbe))

return -ENOEXEC;

if (bprm->java)return -ENOEXEC;

bprm->java = 1;

dput(bprm->dentry);bprm->dentry = NULL;

remove_arg_zero(bprm);len = strlen (bprm->filename);if (len >= 6 && !strcmp (bprm->filename + len - 6, ".class"))

bprm->filename[len - 6] = 0;

Comprueba el númeromágico

No se puede llamarrecursivamente

El fichero javadebe terminar

en “.class”

Page 32: 1 Lección 9: EXEC Tinguaro Tadeo del Rosario Juan José Muñoz García.

32

java handler - do_load_javado_load_java

if ((i_name = strrchr (bprm->filename, '/')) != NULL)i_name++;

elsei_name = bprm->filename;

bprm->p = copy_strings(1, &i_name, bprm->page, bprm->p, 2);bprm->argc++;i_name = binfmt_java_interpreter;bprm->p = copy_strings(1, &i_name, bprm->page, bprm->p, 2);bprm->argc++;

if (!bprm->p) return -E2BIG;

Copia el nombre del intérpretey del fichero .class a la zona de memoria

del proceso, para posteriormenteejecutarlo

Page 33: 1 Lección 9: EXEC Tinguaro Tadeo del Rosario Juan José Muñoz García.

33

java handler - do_load_javado_load_java

bprm->filename = binfmt_java_interpreter;dentry = open_namei(binfmt_java_interpreter, 0, 0);retval = PTR_ERR(dentry);if (IS_ERR(dentry))

return retval;

bprm->dentry = dentry;retval = prepare_binprm(bprm);if (retval < 0)

return retval;

return search_binary_handler(bprm,regs);}

Se ejecuta el intérprete, como se hacía en do_execve:- Comprueba que exista el ejecutable del intérprete- Prepara los argumentos con prepare_binprm- Se busca el manejador para el intérprete (probablemente sea do_load_elf_binary)

Page 34: 1 Lección 9: EXEC Tinguaro Tadeo del Rosario Juan José Muñoz García.

34

java handler - load_javaload_java

De cara al exterior, puede parecer que es la función que realiza la ejecución del .class, pero realmente solo llama a do_load_java

static int load_java(struct linux_binprm *bprm,struct pt_regs *regs){

int retval;MOD_INC_USE_COUNT;retval = do_load_java(bprm,regs);MOD_DEC_USE_COUNT;return retval;

}

Page 35: 1 Lección 9: EXEC Tinguaro Tadeo del Rosario Juan José Muñoz García.

35

FIN


Recommended