Template Information

Trang

Chủ đề

BSP (44) Device Drivers (43) WinCE (38) WINDOWS DRIVER (19) Linux Device Drivers (18) ARM (17) Android tools and tips (17) DRIVER FILES (16) Windows Device Driver (16) AUDIO DRIVER (12) 8051 (8) OMAP (7) PRINTER DRIVER FILES (7) C Programming (6) ASUS MOTHERBOARD (5) Interfacing (5) NETWORK ADAPTER (5) VIDEO DRIVER (5) CANON (3) Device Driver Downloads (3) MOBILE PHONE (3) Asus Driver (2) EPSON (2) Epson Printer Driver (2) HP LAPTOP DRIVER (2) LAPTOP DRIVER FILES (2) Logitech Driver (2) NETWORK ADAPTOR (2) OMAP 4430 (2) drivers download (2) ACER (1) ACER TABLET (1) ALL IN ONE DRIVER (1) Acer Aspire 5738 Drivers (1) Analog-to-Digital (1) Asus Drivers (1) Asus Motherboard Drivers (1) Chip Architecture (1) DELL (1) Dell D610 Drivers (1) Dell Drivers (1) Device Drivers Download (1) Device drivers interview questions (1) Display Driver (1) Drivers Download for Windows 7 (1) EEPROMs (1) Free Asus Motherboard Drivers (1) Free Drivers Download for Windows 7 (1) GRAPHIC DRIVER (1) HP Driver (1) Hardware (1) Intel Drivers (1) Intel P35 (1) Intel P35 chipset drivers (1) I²C (1) LAPTOP SERVICE MANUAL (1) LCD (1) Logitech Mouse Driver (1) Logitech webcam driver (1) MODEM DRIVER (1) Motherboard Drivers for Windows 7 (1) PARALLEL PORT (1) Pc Driver (1) RTOS (1) Real Time Clock (1) Sensors (1) USB CABLE DRIVER (1) WEBCAM DRIVER (1) WIRELESS ADAPTOR (1) Windows 7 Drivers (1) Windows Mobile (1) acer driver (1) acer driver downloads (1) acer laptop driver (1) chipset drivers (1) network card driver (1) network driver download (1) sdcc (1)

Bài viết ngẫu nhiên

Xem phim HD Online

Số lượt views

Manage /proc file with standard filesystem

Thứ Tư, 18 tháng 5, 2011 / 08:45

We have seen how to read and write a /proc file with the /proc interface. But it's also possible to manage /proc file with inodes. The main interest is to use advanced function, like permissions.
In Linux, there is a standard mechanism for file system registration. Since every file system has to have its own functions to handle inode and file operations[1], there is a special structure to hold pointers to all those functions, struct inode_operations, which includes a pointer to struct file_operations. In /proc, whenever we register a new file, we're allowed to specify which struct inode_operations will be used to access to it. This is the mechanism we use, a struct inode_operations which includes a pointer to a struct file_operations which includes pointers to our procfs_read and procfs_write functions.
Another interesting point here is the module_permission function. This function is called whenever a process tries to do something with the /proc file, and it can decide whether to allow access or not. Right now it is only based on the operation and the uid of the current user (as available in current, a pointer to a structure which includes information on the currently running process), but it could be based on anything we like, such as what other processes are doing with the same file, the time of day, or the last input we received.
It's important to note that the standard roles of read and write are reversed in the kernel. Read functions are used for output, whereas write functions are used for input. The reason for that is that read and write refer to the user's point of view --- if a process reads something from the kernel, then the kernel needs to output it, and if a process writes something to the kernel, then the kernel receives it as input.
Example 5-3. procfs3.c
/*
* procfs3.c - create a "file" in /proc, use the file_operation way
* to manage the file.
*/

#include // here linux/kernel.h /* We're doing kernel work */
#include // here linux/module.h /* Specifically, a module */
#include // here linux/proc_fs.h /* Necessary because we use proc fs */
#include // here asm/uaccess.h /* for copy_*_user */

#define PROC_ENTRY_FILENAME "buffer2k"
#define PROCFS_MAX_SIZE 2048

/**
* The buffer (2k) for this module
*
*/
static char procfs_buffer[PROCFS_MAX_SIZE];

/**
* The size of the data hold in the buffer
*
*/
static unsigned long procfs_buffer_size = 0;

/**
* The structure keeping information about the /proc file
*
*/
static struct proc_dir_entry *Our_Proc_File;

/**
* This funtion is called when the /proc file is read
*
*/
static ssize_t procfs_read(struct file *filp, /* see include/linux/fs.h */
char *buffer, /* buffer to fill with data */
size_t length, /* length of the buffer */
loff_t * offset)
{
static int finished = 0;

/*
* We return 0 to indicate end of file, that we have
* no more information. Otherwise, processes will
* continue to read from us in an endless loop.
*/
if ( finished ) {
printk(KERN_INFO "procfs_read: END\n");
finished = 0;
return 0;
}

finished = 1;

/*
* We use put_to_user to copy the string from the kernel's
* memory segment to the memory segment of the process
* that called us. get_from_user, BTW, is
* used for the reverse.
*/
if ( copy_to_user(buffer, procfs_buffer, procfs_buffer_size) ) {
return -EFAULT;
}

printk(KERN_INFO "procfs_read: read %lu bytes\n", procfs_buffer_size);

return procfs_buffer_size; /* Return the number of bytes "read" */
}

/*
* This function is called when /proc is written
*/
static ssize_t
procfs_write(struct file *file, const char *buffer, size_t len, loff_t * off)
{
if ( len > PROCFS_MAX_SIZE ) {
procfs_buffer_size = PROCFS_MAX_SIZE;
}
else {
procfs_buffer_size = len;
}

if ( copy_from_user(procfs_buffer, buffer, procfs_buffer_size) ) {
return -EFAULT;
}

printk(KERN_INFO "procfs_write: write %lu bytes\n", procfs_buffer_size);

return procfs_buffer_size;
}

/*
* This function decides whether to allow an operation
* (return zero) or not allow it (return a non-zero
* which indicates why it is not allowed).
*
* The operation can be one of the following values:
* 0 - Execute (run the "file" - meaningless in our case)
* 2 - Write (input to the kernel module)
* 4 - Read (output from the kernel module)
*
* This is the real function that checks file
* permissions. The permissions returned by ls -l are
* for referece only, and can be overridden here.
*/

static int module_permission(struct inode *inode, int op, struct nameidata *foo)
{
/*
* We allow everybody to read from our module, but
* only root (uid 0) may write to it
*/
if (op == 4 || (op == 2 && current->euid == 0))
return 0;

/*
* If it's anything else, access is denied
*/
return -EACCES;
}

/*
* The file is opened - we don't really care about
* that, but it does mean we need to increment the
* module's reference count.
*/
int procfs_open(struct inode *inode, struct file *file)
{
try_module_get(THIS_MODULE);
return 0;
}

/*
* The file is closed - again, interesting only because
* of the reference count.
*/
int procfs_close(struct inode *inode, struct file *file)
{
module_put(THIS_MODULE);
return 0; /* success */
}

static struct file_operations File_Ops_4_Our_Proc_File = {
.read = procfs_read,
.write = procfs_write,
.open = procfs_open,
.release = procfs_close,
};

/*
* Inode operations for our proc file. We need it so
* we'll have some place to specify the file operations
* structure we want to use, and the function we use for
* permissions. It's also possible to specify functions
* to be called for anything else which could be done to
* an inode (although we don't bother, we just put
* NULL).
*/

static struct inode_operations Inode_Ops_4_Our_Proc_File = {
.permission = module_permission, /* check for permissions */
};

/*
* Module initialization and cleanup
*/
int init_module()
{
/* create the /proc file */
Our_Proc_File = create_proc_entry(PROC_ENTRY_FILENAME, 0644, NULL);

/* check if the /proc file was created successfuly */
if (Our_Proc_File == NULL){
printk(KERN_ALERT "Error: Could not initialize /proc/%s\n",
PROC_ENTRY_FILENAME);
return -ENOMEM;
}

Our_Proc_File->owner = THIS_MODULE;
Our_Proc_File->proc_iops = &Inode_Ops_4_Our_Proc_File;
Our_Proc_File->proc_fops = &File_Ops_4_Our_Proc_File;
Our_Proc_File->mode = S_IFREG | S_IRUGO | S_IWUSR;
Our_Proc_File->uid = 0;
Our_Proc_File->gid = 0;
Our_Proc_File->size = 80;

printk(KERN_INFO "/proc/%s created\n", PROC_ENTRY_FILENAME);

return 0; /* success */
}

void cleanup_module()
{
remove_proc_entry(PROC_ENTRY_FILENAME, &proc_root);
printk(KERN_INFO "/proc/%s removed\n", PROC_ENTRY_FILENAME);
}
Still hungry for procfs examples? Well, first of all keep in mind, there are rumors around, claiming that procfs is on it's way out, consider using sysfs instead. Second, if you really can't get enough, there's a highly recommendable bonus level for procfs below linux/Documentation/DocBook/ . Use make help in your toplevel kernel directory for instructions about how to convert it into your favourite format. Example: make htmldocs . Consider using this mechanism, in case you want to document something kernel related yourself.
Thứ Tư, 18 tháng 5, 2011 08:45 Đọc tiếp >>

Talking to Device Files (writes and IOCTLs)

Device files are supposed to represent physical devices. Most physical devices are used for output as well as input, so there has to be some mechanism for device drivers in the kernel to get the output to send to the device from processes. This is done by opening the device file for output and writing to it, just like writing to a file. In the following example, this is implemented by device_write.
This is not always enough. Imagine you had a serial port connected to a modem (even if you have an internal modem, it is still implemented from the CPU's perspective as a serial port connected to a modem, so you don't have to tax your imagination too hard). The natural thing to do would be to use the device file to write things to the modem (either modem commands or data to be sent through the phone line) and read things from the modem (either responses for commands or the data received through the phone line). However, this leaves open the question of what to do when you need to talk to the serial port itself, for example to send the rate at which data is sent and received.
The answer in Unix is to use a special function called ioctl (short for Input Output ConTroL). Every device can have its own ioctl commands, which can be read ioctl's (to send information from a process to the kernel), write ioctl's (to return information to a process), [1] both or neither. The ioctl function is called with three parameters: the file descriptor of the appropriate device file, the ioctl number, and a parameter, which is of type long so you can use a cast to use it to pass anything. [2]
The ioctl number encodes the major device number, the type of the ioctl, the command, and the type of the parameter. This ioctl number is usually created by a macro call (_IO, _IOR, _IOW or _IOWR --- depending on the type) in a header file. This header file should then be included both by the programs which will use ioctl (so they can generate the appropriate ioctl's) and by the kernel module (so it can understand it). In the example below, the header file is chardev.h and the program which uses it is ioctl.c.
If you want to use ioctls in your own kernel modules, it is best to receive an official ioctl assignment, so if you accidentally get somebody else's ioctls, or if they get yours, you'll know something is wrong. For more information, consult the kernel source tree at Documentation/ioctl-number.txt.

chardev.c
/*
* chardev.c - Create an input/output character device
*/

#include // here linux/kernel.h /* We're doing kernel work */
#include // here linux/module.h /* Specifically, a module */
#include // here linux/fs.h
#include // here asm/uaccess.h /* for get_user and put_user */

#include "chardev.h"
#define SUCCESS 0
#define DEVICE_NAME "char_dev"
#define BUF_LEN 80

/*
* Is the device open right now? Used to prevent
* concurent access into the same device
*/
static int Device_Open = 0;

/*
* The message the device will give when asked
*/
static char Message[BUF_LEN];

/*
* How far did the process reading the message get?
* Useful if the message is larger than the size of the
* buffer we get to fill in device_read.
*/
static char *Message_Ptr;

/*
* This is called whenever a process attempts to open the device file
*/
static int device_open(struct inode *inode, struct file *file)
{
#ifdef DEBUG
printk(KERN_INFO "device_open(%p)\n", file);
#endif

/*
* We don't want to talk to two processes at the same time
*/
if (Device_Open)
return -EBUSY;

Device_Open++;
/*
* Initialize the message
*/
Message_Ptr = Message;
try_module_get(THIS_MODULE);
return SUCCESS;
}

static int device_release(struct inode *inode, struct file *file)
{
#ifdef DEBUG
printk(KERN_INFO "device_release(%p,%p)\n", inode, file);
#endif

/*
* We're now ready for our next caller
*/
Device_Open--;

module_put(THIS_MODULE);
return SUCCESS;
}

/*
* This function is called whenever a process which has already opened the
* device file attempts to read from it.
*/
static ssize_t device_read(struct file *file, /* see include/linux/fs.h */
char __user * buffer, /* buffer to be
* filled with data */
size_t length, /* length of the buffer */
loff_t * offset)
{
/*
* Number of bytes actually written to the buffer
*/
int bytes_read = 0;

#ifdef DEBUG
printk(KERN_INFO "device_read(%p,%p,%d)\n", file, buffer, length);
#endif

/*
* If we're at the end of the message, return 0
* (which signifies end of file)
*/
if (*Message_Ptr == 0)
return 0;

/*
* Actually put the data into the buffer
*/
while (length && *Message_Ptr) {

/*
* Because the buffer is in the user data segment,
* not the kernel data segment, assignment wouldn't
* work. Instead, we have to use put_user which
* copies data from the kernel data segment to the
* user data segment.
*/
put_user(*(Message_Ptr++), buffer++);
length--;
bytes_read++;
}

#ifdef DEBUG
printk(KERN_INFO "Read %d bytes, %d left\n", bytes_read, length);
#endif

/*
* Read functions are supposed to return the number
* of bytes actually inserted into the buffer
*/
return bytes_read;
}

/*
* This function is called when somebody tries to
* write into our device file.
*/
static ssize_t
device_write(struct file *file,
const char __user * buffer, size_t length, loff_t * offset)
{
int i;

#ifdef DEBUG
printk(KERN_INFO "device_write(%p,%s,%d)", file, buffer, length);
#endif

for (i = 0; i < length && i < BUF_LEN; i++)
get_user(Message[i], buffer + i);

Message_Ptr = Message;

/*
* Again, return the number of input characters used
*/
return i;
}

/*
* This function is called whenever a process tries to do an ioctl on our
* device file. We get two extra parameters (additional to the inode and file
* structures, which all device functions get): the number of the ioctl called
* and the parameter given to the ioctl function.
*
* If the ioctl is write or read/write (meaning output is returned to the
* calling process), the ioctl call returns the output of this function.
*
*/
int device_ioctl(struct inode *inode, /* see include/linux/fs.h */
struct file *file, /* ditto */
unsigned int ioctl_num, /* number and param for ioctl */
unsigned long ioctl_param)
{
int i;
char *temp;
char ch;

/*
* Switch according to the ioctl called
*/
switch (ioctl_num) {
case IOCTL_SET_MSG:
/*
* Receive a pointer to a message (in user space) and set that
* to be the device's message. Get the parameter given to
* ioctl by the process.
*/
temp = (char *)ioctl_param;

/*
* Find the length of the message
*/
get_user(ch, temp);
for (i = 0; ch && i < BUF_LEN; i++, temp++)
get_user(ch, temp);

device_write(file, (char *)ioctl_param, i, 0);
break;

case IOCTL_GET_MSG:
/*
* Give the current message to the calling process -
* the parameter we got is a pointer, fill it.
*/
i = device_read(file, (char *)ioctl_param, 99, 0);

/*
* Put a zero at the end of the buffer, so it will be
* properly terminated
*/
put_user('\0', (char *)ioctl_param + i);
break;

case IOCTL_GET_NTH_BYTE:
/*
* This ioctl is both input (ioctl_param) and
* output (the return value of this function)
*/
return Message[ioctl_param];
break;
}

return SUCCESS;
}

/* Module Declarations */

/*
* This structure will hold the functions to be called
* when a process does something to the device we
* created. Since a pointer to this structure is kept in
* the devices table, it can't be local to
* init_module. NULL is for unimplemented functions.
*/
struct file_operations Fops = {
.read = device_read,
.write = device_write,
.ioctl = device_ioctl,
.open = device_open,
.release = device_release, /* a.k.a. close */
};

/*
* Initialize the module - Register the character device
*/
int init_module()
{
int ret_val;
/*
* Register the character device (atleast try)
*/
ret_val = register_chrdev(MAJOR_NUM, DEVICE_NAME, &Fops);

/*
* Negative values signify an error
*/
if (ret_val < 0) {
printk(KERN_ALERT "%s failed with %d\n",
"Sorry, registering the character device ", ret_val);
return ret_val;
}

printk(KERN_INFO "%s The major device number is %d.\n",
"Registeration is a success", MAJOR_NUM);
printk(KERN_INFO "If you want to talk to the device driver,\n");
printk(KERN_INFO "you'll have to create a device file. \n");
printk(KERN_INFO "We suggest you use:\n");
printk(KERN_INFO "mknod %s c %d 0\n", DEVICE_FILE_NAME, MAJOR_NUM);
printk(KERN_INFO "The device file name is important, because\n");
printk(KERN_INFO "the ioctl program assumes that's the\n");
printk(KERN_INFO "file you'll use.\n");

return 0;
}

/*
* Cleanup - unregister the appropriate file from /proc
*/
void cleanup_module()
{
int ret;

/*
* Unregister the device
*/
ret = unregister_chrdev(MAJOR_NUM, DEVICE_NAME);

/*
* If there's an error, report it
*/
if (ret < 0)
printk(KERN_ALERT "Error: unregister_chrdev: %d\n", ret);
}
Example 7-2. chardev.h
/*
* chardev.h - the header file with the ioctl definitions.
*
* The declarations here have to be in a header file, because
* they need to be known both to the kernel module
* (in chardev.c) and the process calling ioctl (ioctl.c)
*/

#ifndef CHARDEV_H
#define CHARDEV_H

#include // here linux/ioctl.h

/*
* The major device number. We can't rely on dynamic
* registration any more, because ioctls need to know
* it.
*/
#define MAJOR_NUM 100

/*
* Set the message of the device driver
*/
#define IOCTL_SET_MSG _IOR(MAJOR_NUM, 0, char *)
/*
* _IOR means that we're creating an ioctl command
* number for passing information from a user process
* to the kernel module.
*
* The first arguments, MAJOR_NUM, is the major device
* number we're using.
*
* The second argument is the number of the command
* (there could be several with different meanings).
*
* The third argument is the type we want to get from
* the process to the kernel.
*/

/*
* Get the message of the device driver
*/
#define IOCTL_GET_MSG _IOR(MAJOR_NUM, 1, char *)
/*
* This IOCTL is used for output, to get the message
* of the device driver. However, we still need the
* buffer to place the message in to be input,
* as it is allocated by the process.
*/

/*
* Get the n'th byte of the message
*/
#define IOCTL_GET_NTH_BYTE _IOWR(MAJOR_NUM, 2, int)
/*
* The IOCTL is used for both input and output. It
* receives from the user a number, n, and returns
* Message[n].
*/

/*
* The name of the device file
*/
#define DEVICE_FILE_NAME "char_dev"

#endif
Example 7-3. ioctl.c
/*
* ioctl.c - the process to use ioctl's to control the kernel module
*
* Until now we could have used cat for input and output. But now
* we need to do ioctl's, which require writing our own process.
*/

/*
* device specifics, such as ioctl numbers and the
* major device file.
*/
#include "chardev.h"

#include // here fcntl.h /* open */
#include // here unistd.h /* exit */
#include // here sys/ioctl.h /* ioctl */

/*
* Functions for the ioctl calls
*/

ioctl_set_msg(int file_desc, char *message)
{
int ret_val;

ret_val = ioctl(file_desc, IOCTL_SET_MSG, message);

if (ret_val < 0) {
printf("ioctl_set_msg failed:%d\n", ret_val);
exit(-1);
}
}

ioctl_get_msg(int file_desc)
{
int ret_val;
char message[100];

/*
* Warning - this is dangerous because we don't tell
* the kernel how far it's allowed to write, so it
* might overflow the buffer. In a real production
* program, we would have used two ioctls - one to tell
* the kernel the buffer length and another to give
* it the buffer to fill
*/
ret_val = ioctl(file_desc, IOCTL_GET_MSG, message);

if (ret_val < 0) {
printf("ioctl_get_msg failed:%d\n", ret_val);
exit(-1);
}

printf("get_msg message:%s\n", message);
}

ioctl_get_nth_byte(int file_desc)
{
int i;
char c;

printf("get_nth_byte message:");

i = 0;
while (c != 0) {
c = ioctl(file_desc, IOCTL_GET_NTH_BYTE, i++);

if (c < 0) {
printf
("ioctl_get_nth_byte failed at the %d'th byte:\n",
i);
exit(-1);
}

putchar(c);
}
putchar('\n');
}

/*
* Main - Call the ioctl functions
*/
main()
{
int file_desc, ret_val;
char *msg = "Message passed by ioctl\n";

file_desc = open(DEVICE_FILE_NAME, 0);
if (file_desc < 0) {
printf("Can't open device file: %s\n", DEVICE_FILE_NAME);
exit(-1);
}

ioctl_get_nth_byte(file_desc);
ioctl_get_msg(file_desc);
ioctl_set_msg(file_desc, msg);

close(file_desc);
}

Notes

[1]Notice that here the roles of read and write are reversed again, so in ioctl's read is to send information to the kernel and write is to receive information from the kernel.
[2]This isn't exact. You won't be able to pass a structure, for example, through an ioctl --- but you will be able to pass a pointer to the structure.
Thứ Tư, 18 tháng 5, 2011 08:44 Đọc tiếp >>

System Calls

System Calls

So far, the only thing we've done was to use well defined kernel mechanisms to register /proc files and device handlers. This is fine if you want to do something the kernel programmers thought you'd want, such as write a device driver. But what if you want to do something unusual, to change the behavior of the system in some way? Then, you're mostly on your own.
This is where kernel programming gets dangerous. While writing the example below, I killed the open() system call. This meant I couldn't open any files, I couldn't run any programs, and I couldn't shutdown the computer. I had to pull the power switch. Luckily, no files died. To ensure you won't lose any files either, please run sync right before you do the insmod and the rmmod.
Forget about /proc files, forget about device files. They're just minor details. The real process to kernel communication mechanism, the one used by all processes, is system calls. When a process requests a service from the kernel (such as opening a file, forking to a new process, or requesting more memory), this is the mechanism used. If you want to change the behaviour of the kernel in interesting ways, this is the place to do it. By the way, if you want to see which system calls a program uses, run strace .
In general, a process is not supposed to be able to access the kernel. It can't access kernel memory and it can't call kernel functions. The hardware of the CPU enforces this (that's the reason why it's called `protected mode').
System calls are an exception to this general rule. What happens is that the process fills the registers with the appropriate values and then calls a special instruction which jumps to a previously defined location in the kernel (of course, that location is readable by user processes, it is not writable by them). Under Intel CPUs, this is done by means of interrupt 0x80. The hardware knows that once you jump to this location, you are no longer running in restricted user mode, but as the operating system kernel --- and therefore you're allowed to do whatever you want.
The location in the kernel a process can jump to is called system_call. The procedure at that location checks the system call number, which tells the kernel what service the process requested. Then, it looks at the table of system calls (sys_call_table) to see the address of the kernel function to call. Then it calls the function, and after it returns, does a few system checks and then return back to the process (or to a different process, if the process time ran out). If you want to read this code, it's at the source file arch/$<$architecture$>$/kernel/entry.S, after the line ENTRY(system_call).
So, if we want to change the way a certain system call works, what we need to do is to write our own function to implement it (usually by adding a bit of our own code, and then calling the original function) and then change the pointer at sys_call_table to point to our function. Because we might be removed later and we don't want to leave the system in an unstable state, it's important for cleanup_module to restore the table to its original state.
The source code here is an example of such a kernel module. We want to `spy' on a certain user, and to printk() a message whenever that user opens a file. Towards this end, we replace the system call to open a file with our own function, called our_sys_open. This function checks the uid (user's id) of the current process, and if it's equal to the uid we spy on, it calls printk() to display the name of the file to be opened. Then, either way, it calls the original open() function with the same parameters, to actually open the file.
The init_module function replaces the appropriate location in sys_call_table and keeps the original pointer in a variable. The cleanup_module function uses that variable to restore everything back to normal. This approach is dangerous, because of the possibility of two kernel modules changing the same system call. Imagine we have two kernel modules, A and B. A's open system call will be A_open and B's will be B_open. Now, when A is inserted into the kernel, the system call is replaced with A_open, which will call the original sys_open when it's done. Next, B is inserted into the kernel, which replaces the system call with B_open, which will call what it thinks is the original system call, A_open, when it's done.
Now, if B is removed first, everything will be well---it will simply restore the system call to A_open, which calls the original. However, if A is removed and then B is removed, the system will crash. A's removal will restore the system call to the original, sys_open, cutting B out of the loop. Then, when B is removed, it will restore the system call to what it thinks is the original, A_open, which is no longer in memory. At first glance, it appears we could solve this particular problem by checking if the system call is equal to our open function and if so not changing it at all (so that B won't change the system call when it's removed), but that will cause an even worse problem. When A is removed, it sees that the system call was changed to B_open so that it is no longer pointing to A_open, so it won't restore it to sys_open before it is removed from memory. Unfortunately, B_open will still try to call A_open which is no longer there, so that even without removing B the system would crash.
Note that all the related problems make syscall stealing unfeasiable for production use. In order to keep people from doing potential harmful things sys_call_table is no longer exported. This means, if you want to do something more than a mere dry run of this example, you will have to patch your current kernel in order to have sys_call_table exported. In the example directory you will find a README and the patch. As you can imagine, such modifications are not to be taken lightly. Do not try this on valueable systems (ie systems that you do not own - or cannot restore easily). You'll need to get the complete sourcecode of this guide as a tarball in order to get the patch and the README. Depending on your kernel version, you might even need to hand apply the patch. Still here? Well, so is this chapter. If Wyle E. Coyote was a kernel hacker, this would be the first thing he'd try. ;)

syscall.c
/*
* syscall.c
*
* System call "stealing" sample.
*/

/*
* Copyright (C) 2001 by Peter Jay Salzman
*/

/*
* The necessary header files
*/

/*
* Standard in kernel modules
*/
#include // here linux/kernel.h /* We're doing kernel work */
#include // here linux/module.h /* Specifically, a module, */
#include // here linux/moduleparam.h /* which will have params */
#include // here linux/unistd.h /* The list of system calls */

/*
* For the current (process) structure, we need
* this to know who the current user is.
*/
#include
#include

/*
* The system call table (a table of functions). We
* just define this as external, and the kernel will
* fill it up for us when we are insmod'ed
*
* sys_call_table is no longer exported in 2.6.x kernels.
* If you really want to try this DANGEROUS module you will
* have to apply the supplied patch against your current kernel
* and recompile it.
*/
extern void *sys_call_table[];

/*
* UID we want to spy on - will be filled from the
* command line
*/
static int uid;
module_param(uid, int, 0644);

/*
* A pointer to the original system call. The reason
* we keep this, rather than call the original function
* (sys_open), is because somebody else might have
* replaced the system call before us. Note that this
* is not 100% safe, because if another module
* replaced sys_open before us, then when we're inserted
* we'll call the function in that module - and it
* might be removed before we are.
*
* Another reason for this is that we can't get sys_open.
* It's a static variable, so it is not exported.
*/
asmlinkage int (*original_call) (const char *, int, int);

/*
* The function we'll replace sys_open (the function
* called when you call the open system call) with. To
* find the exact prototype, with the number and type
* of arguments, we find the original function first
* (it's at fs/open.c).
*
* In theory, this means that we're tied to the
* current version of the kernel. In practice, the
* system calls almost never change (it would wreck havoc
* and require programs to be recompiled, since the system
* calls are the interface between the kernel and the
* processes).
*/
asmlinkage int our_sys_open(const char *filename, int flags, int mode)
{
int i = 0;
char ch;

/*
* Check if this is the user we're spying on
*/
if (uid == current->uid) {
/*
* Report the file, if relevant
*/
printk("Opened file by %d: ", uid);
do {
get_user(ch, filename + i);
i++;
printk("%c", ch);
} while (ch != 0);
printk("\n");
}

/*
* Call the original sys_open - otherwise, we lose
* the ability to open files
*/
return original_call(filename, flags, mode);
}

/*
* Initialize the module - replace the system call
*/
int init_module()
{
/*
* Warning - too late for it now, but maybe for
* next time...
*/
printk(KERN_ALERT "I'm dangerous. I hope you did a ");
printk(KERN_ALERT "sync before you insmod'ed me.\n");
printk(KERN_ALERT "My counterpart, cleanup_module(), is even");
printk(KERN_ALERT "more dangerous. If\n");
printk(KERN_ALERT "you value your file system, it will ");
printk(KERN_ALERT "be \"sync; rmmod\" \n");
printk(KERN_ALERT "when you remove this module.\n");

/*
* Keep a pointer to the original function in
* original_call, and then replace the system call
* in the system call table with our_sys_open
*/
original_call = sys_call_table[__NR_open];
sys_call_table[__NR_open] = our_sys_open;

/*
* To get the address of the function for system
* call foo, go to sys_call_table[__NR_foo].
*/

printk(KERN_INFO "Spying on UID:%d\n", uid);

return 0;
}

/*
* Cleanup - unregister the appropriate file from /proc
*/
void cleanup_module()
{
/*
* Return the system call back to normal
*/
if (sys_call_table[__NR_open] != our_sys_open) {
printk(KERN_ALERT "Somebody else also played with the ");
printk(KERN_ALERT "open system call\n");
printk(KERN_ALERT "The system may be left in ");
printk(KERN_ALERT "an unstable state.\n");
}

sys_call_table[__NR_open] = original_call;
}
Thứ Tư, 18 tháng 5, 2011 08:42 Đọc tiếp >>

Device Drivers Interview Questions

1.What is Device driver?

A device driver is a code that performs device control operations specific to the device being addressed.It is software layer that lies between applications and the actual device.
or
A more formal definition would be Device drivers are distinct black boxes that make a particular piece of hardware respond to a well defined internal programming interface.
or
Device Driver lies between the Hardware & operating system.Through this layer only all the request/response between the OS & H/w are happening.

2.what kind of information the linux driver modules (.ko )files has ?


kernel 2.6 introduces a new file naming convention: kernel modules now have a .ko extension (in place of the old .o extension) which easily distinguishes them from conventional object files. The reason for this is that they contain an additional .modinfo section that where additional information about the module is kept. Linux program modpost can be used to convert .o files into .ko files.
3.what happens when we do insmod & rmmod in Linux Device Drivers ?


At time of insmod required o's brings in ram or updated the kernel with the perticular device driver. At the time of rmmod removes the o's by kmod it kills the process and refresh the kernel.
4.what are the different ways the Linux can swich from User Space to Kernel Space & vice-versa ?



There are 2 situations when Linux can switch from user Space
to Kernel Space:-


1) by doing System calls
2) When interrupt comes (to handle interrupt)


Linux can switch from kernel Space to User space:-
1) process in kernel mode is preempted.
2) After completion of Interrupt handler / System call
Thứ Tư, 18 tháng 5, 2011 08:34 Đọc tiếp >>

How to Install Your ASUS F5 Driver

Thứ Bảy, 12 tháng 2, 2011 / 03:29

There comes a time when your ASUS f5 laptop will slow down in performance for reasons that might not seem clear to you. This reduced performance does not necessarily mean that the laptop needs to be replaced. It could also mean that your drivers are terribly outdated. This is a very regular occurrence given the regularity with which hardware device manufacturers release driver updates. You therefore have to ensure that you have the correct ASUS f5 driver installed in your computer.

The first thing that you have to do is look for the ASUS f5 driver online. You will mostly find it on the manufacturer’s website. If not, it might be found on one of the diverse websites that offer drivers to be downloaded. You have to look for a driver that matches your computer’s operating system.

The task of installing the ASUS f5 driver is rather easy because it comes with simple instructions that you have to follow. The program will prompts you to click on certain places and will therefore lead you through the entire process of installation. You do have to first uninstall any old drivers because its presence will prevent your computer from functioning properly. Even the process of uninstallation of old drivers is very easy. You have to first click on the Start button and go to ‘Add or Remove Programs’. Once you have finished the entire process you should delete the installer for the driver. This will ensure that you free up valuable disk space on your computer.

You will be very pleased with the performance of your computer once you have installed the latest ASUS f5 driver. It will function just like it used to do when you had first bought it if you have completed the installation process correctly. This will save you a lot of time and headache.

Free Download Laptops Driver
Thứ Bảy, 12 tháng 2, 2011 03:29 Đọc tiếp >>

ASUS Eee PC 900 Driver – Get The Correct One For This Small Wonder

Thứ Sáu, 4 tháng 2, 2011 / 02:57

When the ASUS Eee PC 900 notebook hit the market it was an instant hit. This was a compact sized notebook computer that was cheap but which still was packed with a great many features. This notebook computer was considered perfect for carrying around because it could easily fit into a handbag. If you have this notebook computer then you will certainly be pleased with its performance. Needless to say, you do need to make sure that all the software you use is completely up to date in order to get the best performance from this computer. In other words, you need to have the correct ASUS Eee PC 900 drivers installed for the various hardware devices that you use along with this computer.


If you make the mistake of using the wrong ASUS Eee PC 900 drivers there is a great likelihood that your computer will malfunction. Even if it does function reasonably well there will always be certain features that are out of your reach because the software that makes these features work is out of date. You certainly have to be on your toes at all times in order to get the right software for any hardware device for your computer.

Most people just do not have the time to keep themselves updated regarding the status of the software they use. After all, one purchases a computer in order to simplify one’s life and not to complicate it further. If you are terribly hassled at the thought of spending time searching for software then you should just get a driver scan program. This will be an instant solution to your problem because it will be able to download the correct ASUS Eee PC 900 driver and install it so that your computer gives you the best performance.

Laptops Driver Download
Thứ Sáu, 4 tháng 2, 2011 02:57 Đọc tiếp >>

Epson Stylus CX3200 Driver – Ensure That Your Computer Has the Correct One

Thứ Năm, 27 tháng 1, 2011 / 01:51


Have you recently reinstalled Windows or have installed a new version? This can actually cause problems with using your computer since many of your drivers will become out of date. If you have an Epson Stylus CX3200 printer you will immediately start having problems with using it. The problem lies with the Epson Stylus CX3200 driver that your computer has. You will start experiencing many printer device errors due to having the wrong driver.

Device Driver Download

Epson manufactures many printers and each of them has its own driver. Additionally, the drivers can be used only for a particular operating system. The manufacturer puts in a lot of effort to keep these drivers updated so that all performance problems and security issues are corrected. You should therefore ensure that you use only the latest Epson Stylus CX3200 driver rather than the driver that your operating system will suggest. The drivers that the operating system is installed with will always lag behind what the manufacturer releases.

You will have to keep yourself updated regarding the latest driver releases by Epson so that you can immediately install the correct Epson Stylus CX3200 driver on your computer. This will certainly ensure that your printer works well. However this is a time consuming job and most people do not have the time to spare for this.

If you do not have the time for so many follow ups you could always entrust the task to driver update software. The software will scan the internet in order to detect the correct Epson Stylus CX3200 driver. It will then install it in your computer after uninstalling the older version that is no longer up to date. Increasing numbers of people are opting for this method to keep their hardware devices working properly because of the immense convenience it offers.

Free Download Printer Driver.
Thứ Năm, 27 tháng 1, 2011 01:51 Đọc tiếp >>