[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