[Ayuda] MODIFICACIONES AL KERNEL DE LINUX

Ramírez López Jorge jramirlo en banxico.org.mx
Mar Ene 8 17:30:34 CST 2002


A QUIEN CORRESPONDA

Quisiera que me dijeran, por favor, en donde puedo obtener ayuda
especifica sobre problemas que tengo al modificar las funciones sys_open
y sys_close de /usr/src/linux/fs/open.c .

A continuacion describo el problema especifico de que se trata.


Distribucion: RedHat 6.2
Kernel: 2.2.16-3

Estoy tratando de hacer algunas modificaciones en las funciones sys_open

y sys_close en /usr/src/linux/fs/open.c . Curiosamente, no tengo
problemas en hacer las modificaciones que necesito en sys_open, pero no
se me permiten en sys_close. Concretamente se trata de lo siguiente:



/*
 *  linux/fs/open.c
 *
 *  Copyright (C) 1991, 1992  Linus Torvalds
 */

#include <linux/mm.h>
#include <linux/utime.h>
#include <linux/file.h>
#include <linux/smp_lock.h>
#include <linux/quotaops.h>

#include <asm/uaccess.h>

#include <linux/un.h>

#define FILE_UNIX  "/tmp/file_unix"

struct peticion
   {
   /* peticion.tipo_msj :
            1=peticion de open;
            2=aviso de close;
            3=fin de sincronia */
   int tipo_msj;
   int proceso;
   int file;
   char file_name [250];
   };


asmlinkage int sys_open(const char * filename, int flags, int mode)
{
        char * tmp;
        int fd, error;

/*
------------------------------------------------------------------------------

*/
        struct sockaddr_un serv_addr;
        int sock_id, serv_addr_len;
        struct peticion * request;
        int * respuesta;

        if ( sys_getuid() >= 1000 &&
             ((flags & O_APPEND) ||
             (flags & O_CREAT) ||
             (flags & O_RDWR) ||
             (flags & O_SYNC) ||
             (flags & O_TRUNC) ||
             (flags & O_WRONLY)) )
           {
           respuesta = (int *) vmalloc (sizeof(int));
           request = (struct peticion *) vmalloc (sizeof(struct
peticion));

           tmp = getname(filename);
           *respuesta = 0;
           request->tipo_msj = 1;
           request->proceso = sys_getpid();
           strcpy (request->file_name, tmp);
           serv_addr.sun_family = AF_UNIX;
           strcpy (serv_addr.sun_path, FILE_UNIX);
           serv_addr_len = strlen (serv_addr.sun_path) + sizeof
(serv_addr.sun_family);

           if ( (sock_id = sys_socket (AF_UNIX, SOCK_STREAM, 0)) == -1 )

              goto pre_error;

           if ( sys_connect (sock_id, (struct sockaddr *) &serv_addr,
serv_addr_len) == -1 )
              goto pre_error;

           if ( sys_sendto (sock_id, request, sizeof (request), 0,
                (struct sockkaddr *) &serv_addr, sizeof (serv_addr)) !=
sizeof (request) )
              goto pre_error;

           if ( sys_recvfrom (sock_id, respuesta, sizeof (int), 0, NULL,

NULL) == -1 )
              goto pre_error;

           /* si la respuesta es cero ==> fue negado el acceso al
archivo */
           if ( *respuesta == 0)
              goto pre_error;
           else
              goto salida_ok;

           pre_error:
              sys_close (sock_id);
              vfree (respuesta);
              vfree (request);
              error=-EACCES;
              fd = -1;
              return fd;

           salida_ok:
              sys_close (sock_id);
              vfree (respuesta);
              vfree (request);
           }
/*
------------------------------------------------------------------------------

*/

        tmp = getname(filename);
        fd = PTR_ERR(tmp);
        if (!IS_ERR(tmp)) {
                lock_kernel();
                fd = get_unused_fd();
                if (fd >= 0) {
                        struct file * f = filp_open(tmp, flags, mode);
                        error = PTR_ERR(f);
                        if (IS_ERR(f))
                                goto out_error;
                        fd_install(fd, f);
                }

out:
                unlock_kernel();
                putname(tmp);
        }
        return fd;

out_error:
        put_unused_fd(fd);
        fd = error;
        goto out;
}


asmlinkage int sys_close(unsigned int fd)
{
        int error;
        struct file * filp;

        struct sockaddr_un serv_addr;
        int sock_id, serv_addr_len;
        struct peticion * request;
        unsigned int fd_back;
        int archivo=0;

        fd_back = fd;
        /* si lo siguiente se cumple entonces se trata de un archivo, no

de un socket */
        if ( current->files->fd[fd]->f_dentry->d_inode->i_dev != 0 )
           archivo =1;

        lock_kernel();
        error = -EBADF;
        filp = fcheck(fd);
        if (filp) {
                struct files_struct * files = current->files;
                files->fd[fd] = NULL;
                put_unused_fd(fd);
                FD_CLR(fd, files->close_on_exec);
                error = filp_close(filp, files);
        }
        unlock_kernel();

/*
------------------------------------------------------------------------------

*/
        if ( sys_getuid() >= 1000 && (archivo==1) )
           {
           request = (struct peticion *) vmalloc (sizeof(struct
peticion));
           request->tipo_msj = 2;
           request->proceso = sys_getpid();
           request->file = fd_back;
           strcpy (request->file_name,
current->files->fd[fd]->f_dentry->d_name.name);
           serv_addr.sun_family = AF_UNIX;
           strcpy (serv_addr.sun_path, FILE_UNIX);
           serv_addr_len = strlen (serv_addr.sun_path) + sizeof
(serv_addr.sun_family);

           if ( (sock_id = sys_socket (AF_UNIX, SOCK_STREAM, 0)) != -1 )

              if ( sys_connect (sock_id, (struct sockaddr *) &serv_addr,

serv_addr_len) != -1 )
                 sys_sendto (sock_id, request, sizeof (request), 0,
                             (struct sockkaddr *) &serv_addr, sizeof
(serv_addr));

           new_close (sock_id);
           vfree (request);
           }
/*
------------------------------------------------------------------------------

*/

        return error;
}



El problema no viene en la compilacion, sino en la ejecucion. Esto es, a

la hora de arrancar el sistema operativo se queda bloqueado con el
siguiente mensaje en la pantalla:

------------------------------------------------------------------------------------------

VFS: Mounted root (ext2 filesystem) readonly.
Freeing unused kernel memory: 64 k freed.
Unable to handle kernel NULL pointer dereference at virtual adress
00000008
current->tss.cr3 = 07e4c000, %cr3 = 07e4c000
*pde = 00000000
Oops: 0000
CPU:       0
EIP:          0010:[<c0126525>]
EFLAGS: 00010286
------------------------------------------------------------------------------------------

y continua un dump de los registros del procesador y otras cosas. Si se
ejecuta lo que se indica en /usr/src/linux/README:

              nm vmlinux | sort | less

se encuentra que la funcion que marca error ( c0126525 ) es
efectivamente sys_close.

Por otro lado, he intentado hacer pruebas con una seccion de codigo
mucho mas sencillo en sys_close, como la siguiente:


/*
------------------------------------------------------------------------------

*/
        if ( sys_getuid() >= 1000 && (archivo==1) )
           {
            char prueba [250];

            prueba [0] = 2;

           }
/*
------------------------------------------------------------------------------

*/

y esto basta para marcar el mismo problema.

No se si ustedes ya hayan tenido alguna experiencia similar y pudieran
orientarme al respecto. Gracias.


Atantamente

Jorge Ramirez
Banco de Mexico.

_______________________________________________
Ayuda mailing list
Ayuda en linux.org.mx



Más información sobre la lista de distribución Ayuda