1
0
mirror of https://github.com/bashrc/LKMPG.git synced 2018-06-11 03:06:54 +02:00

Merge pull request #4 from SunyDays/master

fix ioctl example erro (_IOW needed instead _IOR)
This commit is contained in:
Bob Mottram
2017-03-11 19:38:49 +00:00
committed by GitHub
21 changed files with 298 additions and 80 deletions

View File

@@ -1421,7 +1421,7 @@ Kernel modules are different here, too. In the hello world example, you might ha
</p>
<p>
One point to keep in mind is the difference between library functions and system calls. Library functions are higher level, run completely in user space and provide a more convenient interface for the programmer to the functions that do the real work&#x2014;system calls. System calls run in kernel mode on the user's behalf and are provided by the kernel itself. The library function printf() may look like a very general printing function, but all it really does is format the data into strings and write the string data using the low-level system call write(), which then sends the data to standard output.
One point to keep in mind is the difference between library functions and system calls. Library functions are higher level, run completely in user space and provide a more convenient interface for the programmer to the functions that do the real work &#x2014; system calls. System calls run in kernel mode on the user's behalf and are provided by the kernel itself. The library function printf() may look like a very general printing function, but all it really does is format the data into strings and write the string data using the low-level system call write(), which then sends the data to standard output.
</p>
<p>
@@ -1483,7 +1483,7 @@ The file <b>/proc/kallsyms</b> holds all the symbols that the kernel knows about
<h3 id="orgd489a2d">Code space</h3>
<div class="outline-text-3" id="text-orgd489a2d">
<p>
Memory management is a very complicated subject&#x2014;the majority of O'Reilly's "<i>Understanding The Linux Kernel</i>" is just on memory management! We're not setting out to be experts on memory managements, but we do need to know a couple of facts to even begin worrying about writing real modules.
Memory management is a very complicated subject &#x2014; the majority of O'Reilly's "<i>Understanding The Linux Kernel</i>" is just on memory management! We're not setting out to be experts on memory managements, but we do need to know a couple of facts to even begin worrying about writing real modules.
</p>
<p>
@@ -2953,9 +2953,9 @@ If you want to use ioctls in your own kernel modules, it is best to receive an o
<span class="org-comment-delimiter">/*</span>
<span class="org-comment"> * Set the message of the device driver</span>
<span class="org-comment"> </span><span class="org-comment-delimiter">*/</span>
<span class="org-preprocessor">#define</span> <span class="org-variable-name">IOCTL_SET_MSG</span> _IOR(MAJOR_NUM, 0, <span class="org-type">char</span> *)
<span class="org-preprocessor">#define</span> <span class="org-variable-name">IOCTL_SET_MSG</span> _IOW(MAJOR_NUM, 0, <span class="org-type">char</span> *)
<span class="org-comment-delimiter">/*</span>
<span class="org-comment"> * _IOR means that we're creating an ioctl command</span>
<span class="org-comment"> * _IOW means that we're creating an ioctl command</span>
<span class="org-comment"> * number for passing information from a user process</span>
<span class="org-comment"> * to the kernel module.</span>
<span class="org-comment"> *</span>
@@ -3151,7 +3151,7 @@ The <b>init_module</b> function replaces the appropriate location in <b>sys_call
</p>
<p>
Now, if B is removed first, everything will be well&#x2014;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, <b>A_open</b>, 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>B_open</b> so that it is no longer pointing to <b>A_open</b>, so it won't restore it to <b>sys_open</b> before it is removed from memory. Unfortunately, <b>B_open</b> will still try to call <b>A_open</b> which is no longer there, so that even without removing B the system would crash.
Now, if B is removed first, everything will be well &#x2014; 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, <b>A_open</b>, 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>B_open</b> so that it is no longer pointing to <b>A_open</b>, so it won't restore it to <b>sys_open</b> before it is removed from memory. Unfortunately, <b>B_open</b> will still try to call <b>A_open</b> which is no longer there, so that even without removing B the system would crash.
</p>
<p>

View File

@@ -661,7 +661,7 @@ Programmers use functions they don't define all the time. A prime example of thi
Kernel modules are different here, too. In the hello world example, you might have noticed that we used a function, *printk()* but didn't include a standard I/O library. That's because modules are object files whose symbols get resolved upon insmod'ing. The definition for the symbols comes from the kernel itself; the only external functions you can use are the ones provided by the kernel. If you're curious about what symbols have been exported by your kernel, take a look at */proc/kallsyms*.
One point to keep in mind is the difference between library functions and system calls. Library functions are higher level, run completely in user space and provide a more convenient interface for the programmer to the functions that do the real work---system calls. System calls run in kernel mode on the user's behalf and are provided by the kernel itself. The library function printf() may look like a very general printing function, but all it really does is format the data into strings and write the string data using the low-level system call write(), which then sends the data to standard output.
One point to keep in mind is the difference between library functions and system calls. Library functions are higher level, run completely in user space and provide a more convenient interface for the programmer to the functions that do the real work --- system calls. System calls run in kernel mode on the user's behalf and are provided by the kernel itself. The library function printf() may look like a very general printing function, but all it really does is format the data into strings and write the string data using the low-level system call write(), which then sends the data to standard output.
Would you like to see what system calls are made by printf()? It's easy! Compile the following program:
@@ -695,7 +695,7 @@ The file */proc/kallsyms* holds all the symbols that the kernel knows about and
** Code space
Memory management is a very complicated subject---the majority of O'Reilly's "/Understanding The Linux Kernel/" is just on memory management! We're not setting out to be experts on memory managements, but we do need to know a couple of facts to even begin worrying about writing real modules.
Memory management is a very complicated subject --- the majority of O'Reilly's "/Understanding The Linux Kernel/" is just on memory management! We're not setting out to be experts on memory managements, but we do need to know a couple of facts to even begin worrying about writing real modules.
If you haven't thought about what a segfault really means, you may be surprised to hear that pointers don't actually point to memory locations. Not real ones, anyway. When a process is created, the kernel sets aside a portion of real physical memory and hands it to the process to use for its executing code, variables, stack, heap and other things which a computer scientist would know about[5]. This memory begins with 0x00000000 and extends up to whatever it needs to be. Since the memory space for any two processes don't overlap, every process that can access a memory address, say 0xbffff978, would be accessing a different location in real physical memory! The processes would be accessing an index named 0xbffff978 which points to some kind of offset into the region of memory set aside for that particular process. For the most part, a process like our Hello, World program can't access the space of another process, although there are ways which we'll talk about later.
@@ -1931,9 +1931,9 @@ void cleanup_module()
/*
* Set the message of the device driver
*/
#define IOCTL_SET_MSG _IOR(MAJOR_NUM, 0, char *)
#define IOCTL_SET_MSG _IOW(MAJOR_NUM, 0, char *)
/*
* _IOR means that we're creating an ioctl command
* _IOW means that we're creating an ioctl command
* number for passing information from a user process
* to the kernel module.
*

View File

@@ -708,7 +708,7 @@ Programmers use functions they don't define all the time. A prime example of thi
Kernel modules are different here, too. In the hello world example, you might have noticed that we used a function, printk() but didn't include a standard I/O library. That's because modules are object files whose symbols get resolved upon insmod'ing. The definition for the symbols comes from the kernel itself; the only external functions you can use are the ones provided by the kernel. If you're curious about what symbols have been exported by your kernel, take a look at /proc/kallsyms.
One point to keep in mind is the difference between library functions and system calls. Library functions are higher level, run completely in user space and provide a more convenient interface for the programmer to the functions that do the real work---system calls. System calls run in kernel mode on the user's behalf and are provided by the kernel itself. The library function printf() may look like a very general printing function, but all it really does is format the data into strings and write the string data using the low-level system call write(), which then sends the data to standard output.
One point to keep in mind is the difference between library functions and system calls. Library functions are higher level, run completely in user space and provide a more convenient interface for the programmer to the functions that do the real work --- system calls. System calls run in kernel mode on the user's behalf and are provided by the kernel itself. The library function printf() may look like a very general printing function, but all it really does is format the data into strings and write the string data using the low-level system call write(), which then sends the data to standard output.
Would you like to see what system calls are made by printf()? It's easy! Compile the following program:
@@ -742,7 +742,7 @@ The file */proc/kallsyms* holds all the symbols that the kernel knows about and
** Code space
Memory management is a very complicated subject---the majority of O'Reilly's `Understanding The Linux Kernel' is just on memory management! We're not setting out to be experts on memory managements, but we do need to know a couple of facts to even begin worrying about writing real modules.
Memory management is a very complicated subject --- the majority of O'Reilly's `Understanding The Linux Kernel' is just on memory management! We're not setting out to be experts on memory managements, but we do need to know a couple of facts to even begin worrying about writing real modules.
If you haven't thought about what a segfault really means, you may be surprised to hear that pointers don't actually point to memory locations. Not real ones, anyway. When a process is created, the kernel sets aside a portion of real physical memory and hands it to the process to use for its executing code, variables, stack, heap and other things which a computer scientist would know about[5]. This memory begins with 0x00000000 and extends up to whatever it needs to be. Since the memory space for any two processes don't overlap, every process that can access a memory address, say 0xbffff978, would be accessing a different location in real physical memory! The processes would be accessing an index named 0xbffff978 which points to some kind of offset into the region of memory set aside for that particular process. For the most part, a process like our Hello, World program can't access the space of another process, although there are ways which we'll talk about later.
@@ -2045,9 +2045,9 @@ void cleanup_module()
/*
* Set the message of the device driver
*/
#define IOCTL_SET_MSG _IOR(MAJOR_NUM, 0, char *)
#define IOCTL_SET_MSG _IOW(MAJOR_NUM, 0, char *)
/*
* _IOR means that we're creating an ioctl command
* _IOW means that we're creating an ioctl command
* number for passing information from a user process
* to the kernel module.
*
@@ -2214,7 +2214,7 @@ The source code here is an example of such a kernel module. We want to `spy' on
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.
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. ;)

View File

@@ -1241,7 +1241,7 @@ Kernel modules are different here, too. In the hello world example, you might ha
</p>
<p>
One point to keep in mind is the difference between library functions and system calls. Library functions are higher level, run completely in user space and provide a more convenient interface for the programmer to the functions that do the real work&#x2014;system calls. System calls run in kernel mode on the user's behalf and are provided by the kernel itself. The library function printf() may look like a very general printing function, but all it really does is format the data into strings and write the string data using the low-level system call write(), which then sends the data to standard output.
One point to keep in mind is the difference between library functions and system calls. Library functions are higher level, run completely in user space and provide a more convenient interface for the programmer to the functions that do the real work &#x2014; system calls. System calls run in kernel mode on the user's behalf and are provided by the kernel itself. The library function printf() may look like a very general printing function, but all it really does is format the data into strings and write the string data using the low-level system call write(), which then sends the data to standard output.
</p>
<p>
@@ -2444,7 +2444,7 @@ If you want to use ioctls in your own kernel modules, it is best to receive an o
<span class="org-preprocessor">#include</span> <span class="org-string">&lt;linux/fs.h&gt;</span>
<span class="org-preprocessor">#include</span> <span class="org-string">&lt;asm/uaccess.h&gt;</span> <span class="org-comment-delimiter">/* </span><span class="org-comment">for get_user and put_user </span><span class="org-comment-delimiter">*/</span>
<span class="org-preprocessor">#include</span> <span class="org-string">"chardev2.h"</span>
<span class="org-preprocessor">#include</span> <span class="org-string">"chardev.h"</span>
<span class="org-preprocessor">#define</span> <span class="org-variable-name">SUCCESS</span> 0
<span class="org-preprocessor">#define</span> <span class="org-variable-name">DEVICE_NAME</span> <span class="org-string">"char_dev"</span>
<span class="org-preprocessor">#define</span> <span class="org-variable-name">BUF_LEN</span> 80
@@ -2738,9 +2738,9 @@ If you want to use ioctls in your own kernel modules, it is best to receive an o
<span class="org-comment-delimiter">/*</span>
<span class="org-comment"> * Set the message of the device driver</span>
<span class="org-comment"> </span><span class="org-comment-delimiter">*/</span>
<span class="org-preprocessor">#define</span> <span class="org-variable-name">IOCTL_SET_MSG</span> _IOR(MAJOR_NUM, 0, <span class="org-type">char</span> *)
<span class="org-preprocessor">#define</span> <span class="org-variable-name">IOCTL_SET_MSG</span> _IOW(MAJOR_NUM, 0, <span class="org-type">char</span> *)
<span class="org-comment-delimiter">/*</span>
<span class="org-comment"> * _IOR means that we're creating an ioctl command</span>
<span class="org-comment"> * _IOW means that we're creating an ioctl command</span>
<span class="org-comment"> * number for passing information from a user process</span>
<span class="org-comment"> * to the kernel module.</span>
<span class="org-comment"> *</span>
@@ -2796,7 +2796,7 @@ If you want to use ioctls in your own kernel modules, it is best to receive an o
<span class="org-comment"> * device specifics, such as ioctl numbers and the</span>
<span class="org-comment"> * major device file.</span>
<span class="org-comment"> </span><span class="org-comment-delimiter">*/</span>
<span class="org-preprocessor">#include</span> <span class="org-string">"chardev.h"</span>
<span class="org-preprocessor">#include</span> <span class="org-string">"../chardev.h"</span>
<span class="org-preprocessor">#include</span> <span class="org-string">&lt;stdio.h&gt;</span>
<span class="org-preprocessor">#include</span> <span class="org-string">&lt;stdlib.h&gt;</span>
@@ -2934,7 +2934,7 @@ The <b>init_module</b> function replaces the appropriate location in <b>sys_call
</p>
<p>
Now, if B is removed first, everything will be well&#x2014;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, <b>A_open</b>, 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>B_open</b> so that it is no longer pointing to <b>A_open</b>, so it won't restore it to <b>sys_open</b> before it is removed from memory. Unfortunately, <b>B_open</b> will still try to call <b>A_open</b> which is no longer there, so that even without removing B the system would crash.
Now, if B is removed first, everything will be well &#x2014; 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, <b>A_open</b>, 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>B_open</b> so that it is no longer pointing to <b>A_open</b>, so it won't restore it to <b>sys_open</b> before it is removed from memory. Unfortunately, <b>B_open</b> will still try to call <b>A_open</b> which is no longer there, so that even without removing B the system would crash.
</p>
<p>

View File

@@ -612,7 +612,7 @@ Programmers use functions they don't define all the time. A prime example of thi
Kernel modules are different here, too. In the hello world example, you might have noticed that we used a function, *printk()* but didn't include a standard I/O library. That's because modules are object files whose symbols get resolved upon insmod'ing. The definition for the symbols comes from the kernel itself; the only external functions you can use are the ones provided by the kernel. If you're curious about what symbols have been exported by your kernel, take a look at */proc/kallsyms*.
One point to keep in mind is the difference between library functions and system calls. Library functions are higher level, run completely in user space and provide a more convenient interface for the programmer to the functions that do the real work---system calls. System calls run in kernel mode on the user's behalf and are provided by the kernel itself. The library function printf() may look like a very general printing function, but all it really does is format the data into strings and write the string data using the low-level system call write(), which then sends the data to standard output.
One point to keep in mind is the difference between library functions and system calls. Library functions are higher level, run completely in user space and provide a more convenient interface for the programmer to the functions that do the real work --- system calls. System calls run in kernel mode on the user's behalf and are provided by the kernel itself. The library function printf() may look like a very general printing function, but all it really does is format the data into strings and write the string data using the low-level system call write(), which then sends the data to standard output.
Would you like to see what system calls are made by printf()? It's easy! Compile the following program:
@@ -1063,7 +1063,7 @@ The reason for copy_from_user or get_user is that Linux memory (on Intel archite
The only memory segment accessible to a process is its own, so when writing regular programs to run as processes, there's no need to worry about segments. When you write a kernel module, normally you want to access the kernel memory segment, which is handled automatically by the system. However, when the content of a memory buffer needs to be passed between the currently running process and the kernel, the kernel function receives a pointer to the memory buffer which is in the process segment. The put_user and get_user macros allow you to access that memory. These functions handle only one caracter, you can handle several caracters with copy_to_user and copy_from_user. As the buffer (in read or write function) is in kernel space, for write function you need to import data because it comes from user space, but not for the read function because data is already in kernel space.
#+BEGIN_SRC c
#+BEGIN_SRC c :file procfs2.c
/**
* procfs2.c - create a "file" in /proc
*
@@ -1173,7 +1173,7 @@ Another interesting point here is the module_permission function. This function
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.
#+BEGIN_SRC c
#+BEGIN_SRC c :file procfs3.c
/*
procfs3.c
*/
@@ -1298,7 +1298,7 @@ digraph seq_file {
|
Seq_file provides basic functions for file_operations, as seq_read, seq_lseek, and some others. But nothing to write in the /proc file. Of course, you can still use the same way as in the previous example.
#+BEGIN_SRC c
#+BEGIN_SRC c :file procfs4.c
/**
* procfs4.c - create a "file" in /proc
* This program uses the seq_file library to manage the /proc file.
@@ -1573,7 +1573,7 @@ If you want to use ioctls in your own kernel modules, it is best to receive an o
#include <linux/fs.h>
#include <asm/uaccess.h> /* for get_user and put_user */
#include "chardev2.h"
#include "chardev.h"
#define SUCCESS 0
#define DEVICE_NAME "char_dev"
#define BUF_LEN 80
@@ -1866,9 +1866,9 @@ void cleanup_module()
/*
* Set the message of the device driver
*/
#define IOCTL_SET_MSG _IOR(MAJOR_NUM, 0, char *)
#define IOCTL_SET_MSG _IOW(MAJOR_NUM, 0, char *)
/*
* _IOR means that we're creating an ioctl command
* _IOW means that we're creating an ioctl command
* number for passing information from a user process
* to the kernel module.
*
@@ -1911,7 +1911,7 @@ void cleanup_module()
#endif
#+END_SRC
#+BEGIN_SRC c :file ioctl.c
#+BEGIN_SRC c :file other/ioctl.c
/*
* ioctl.c - the process to use ioctl's to control the kernel module
*
@@ -1923,7 +1923,7 @@ void cleanup_module()
* device specifics, such as ioctl numbers and the
* major device file.
*/
#include "chardev.h"
#include "../chardev.h"
#include <stdio.h>
#include <stdlib.h>
@@ -2037,7 +2037,7 @@ The source code here is an example of such a kernel module. We want to "spy" on
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.
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. ;)
@@ -2501,7 +2501,7 @@ void cleanup_module()
}
#+END_SRC
#+BEGIN_SRC c :file cat_noblock.c
#+BEGIN_SRC c :file other/cat_noblock.c
/* cat_noblock.c - open a file and display its contents, but exit rather than
* wait for input */
/* Copyright (C) 1998 by Ori Pomerantz */

View File

@@ -14,7 +14,7 @@ obj-m += hello-sysfs.o
obj-m += sleep.o
obj-m += print_string.o
obj-m += kbleds.o
obj-m += file_sched.o
obj-m += sched.o
obj-m += chardev2.o
obj-m += syscall.o

View File

@@ -108,7 +108,7 @@ static int device_release(struct inode *inode, struct file *file)
*/
module_put(THIS_MODULE);
return 0;
return SUCCESS;
}
/*
@@ -158,8 +158,10 @@ static ssize_t device_read(struct file *filp, /* see include/linux/fs.h */
/*
* Called when a process writes to dev file: echo "hi" > /dev/hello
*/
static ssize_t
device_write(struct file *filp, const char *buff, size_t len, loff_t * off)
static ssize_t device_write(struct file *filp,
const char *buff,
size_t len,
loff_t * off)
{
printk(KERN_ALERT "Sorry, this operation isn't supported.\n");
return -EINVAL;

View File

@@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>clang_version</key>
<string>clang version 3.8.1 (tags/RELEASE_381/final)</string>
<key>files</key>
<array>
</array>
<key>diagnostics</key>
<array>
</array>
</dict>
</plist>

113
4.7.4/examples/intrpt.c Normal file
View File

@@ -0,0 +1,113 @@
/*
* intrpt.c - An interrupt handler.
*
* Copyright (C) 2001 by Peter Jay Salzman
*/
/*
* The necessary header files
*/
/*
* Standard in kernel modules
*/
#include <linux/kernel.h> /* We're doing kernel work */
#include <linux/module.h> /* Specifically, a module */
#include <linux/sched.h>
#include <linux/workqueue.h>
#include <linux/interrupt.h> /* We want an interrupt */
#include <asm/io.h>
#define MY_WORK_QUEUE_NAME "WQsched.c"
static struct workqueue_struct *my_workqueue;
/*
* This will get called by the kernel as soon as it's safe
* to do everything normally allowed by kernel modules.
*/
static void got_char(void *scancode)
{
printk(KERN_INFO "Scan Code %x %s.\n",
(int)*((char *)scancode) & 0x7F,
*((char *)scancode) & 0x80 ? "Released" : "Pressed");
}
/*
* This function services keyboard interrupts. It reads the relevant
* information from the keyboard and then puts the non time critical
* part into the work queue. This will be run when the kernel considers it safe.
*/
irqreturn_t irq_handler(int irq, void *dev_id, struct pt_regs *regs)
{
/*
* This variables are static because they need to be
* accessible (through pointers) to the bottom half routine.
*/
static int initialised = 0;
static unsigned char scancode;
static struct work_struct task;
unsigned char status;
/*
* Read keyboard status
*/
status = inb(0x64);
scancode = inb(0x60);
if (initialised == 0) {
INIT_WORK(&task, got_char, &scancode);
initialised = 1;
} else {
PREPARE_WORK(&task, got_char, &scancode);
}
queue_work(my_workqueue, &task);
return IRQ_HANDLED;
}
/*
* Initialize the module - register the IRQ handler
*/
int init_module()
{
my_workqueue = create_workqueue(MY_WORK_QUEUE_NAME);
/*
* Since the keyboard handler won't co-exist with another handler,
* such as us, we have to disable it (free its IRQ) before we do
* anything. Since we don't know where it is, there's no way to
* reinstate it later - so the computer will have to be rebooted
* when we're done.
*/
free_irq(1, NULL);
/*
* Request IRQ 1, the keyboard IRQ, to go to our irq_handler.
* SA_SHIRQ means we're willing to have othe handlers on this IRQ.
* SA_INTERRUPT can be used to make the handler into a fast interrupt.
*/
return request_irq(1, /* The number of the keyboard IRQ on PCs */
irq_handler, /* our handler */
SA_SHIRQ, "test_keyboard_irq_handler",
(void *)(irq_handler));
}
/*
* Cleanup
*/
void cleanup_module()
{
/*
* This is only here for completeness. It's totally irrelevant, since
* we don't have a way to restore the normal keyboard interrupt so the
* computer is completely useless and has to be rebooted.
*/
free_irq(1, NULL);
}
/*
* some work_queue related functions are just available to GPL licensed Modules
*/
MODULE_LICENSE("GPL");

BIN
4.7.4/examples/other/cat_noblock Executable file

Binary file not shown.

BIN
4.7.4/examples/other/ioctl Executable file

Binary file not shown.

View File

@@ -30,7 +30,7 @@ static void print_string(char *str)
/*
* The tty for the current task, for 2.6.6+ kernels
*/
my_tty = current->signal->tty;
my_tty = get_current_tty();
#endif
ttyops = my_tty->driver->ops;

View File

@@ -1255,7 +1255,7 @@ Kernel modules are different here, too. In the hello world example, you might ha
</p>
<p>
One point to keep in mind is the difference between library functions and system calls. Library functions are higher level, run completely in user space and provide a more convenient interface for the programmer to the functions that do the real work&#x2014;system calls. System calls run in kernel mode on the user's behalf and are provided by the kernel itself. The library function printf() may look like a very general printing function, but all it really does is format the data into strings and write the string data using the low-level system call write(), which then sends the data to standard output.
One point to keep in mind is the difference between library functions and system calls. Library functions are higher level, run completely in user space and provide a more convenient interface for the programmer to the functions that do the real work &#x2014; system calls. System calls run in kernel mode on the user's behalf and are provided by the kernel itself. The library function printf() may look like a very general printing function, but all it really does is format the data into strings and write the string data using the low-level system call write(), which then sends the data to standard output.
</p>
<p>
@@ -1696,7 +1696,7 @@ The next code sample creates a char driver named chardev. You can cat its device
<span class="org-comment"> </span><span class="org-comment-delimiter">*/</span>
module_put(THIS_MODULE);
<span class="org-keyword">return</span> 0;
<span class="org-keyword">return</span> SUCCESS;
}
<span class="org-comment-delimiter">/*</span>
@@ -2463,7 +2463,7 @@ If you want to use ioctls in your own kernel modules, it is best to receive an o
<span class="org-preprocessor">#include</span> <span class="org-string">&lt;linux/fs.h&gt;</span>
<span class="org-preprocessor">#include</span> <span class="org-string">&lt;asm/uaccess.h&gt;</span> <span class="org-comment-delimiter">/* </span><span class="org-comment">for get_user and put_user </span><span class="org-comment-delimiter">*/</span>
<span class="org-preprocessor">#include</span> <span class="org-string">"chardev2.h"</span>
<span class="org-preprocessor">#include</span> <span class="org-string">"chardev.h"</span>
<span class="org-preprocessor">#define</span> <span class="org-variable-name">SUCCESS</span> 0
<span class="org-preprocessor">#define</span> <span class="org-variable-name">DEVICE_NAME</span> <span class="org-string">"char_dev"</span>
<span class="org-preprocessor">#define</span> <span class="org-variable-name">BUF_LEN</span> 80
@@ -2757,9 +2757,9 @@ If you want to use ioctls in your own kernel modules, it is best to receive an o
<span class="org-comment-delimiter">/*</span>
<span class="org-comment"> * Set the message of the device driver</span>
<span class="org-comment"> </span><span class="org-comment-delimiter">*/</span>
<span class="org-preprocessor">#define</span> <span class="org-variable-name">IOCTL_SET_MSG</span> _IOR(MAJOR_NUM, 0, <span class="org-type">char</span> *)
<span class="org-preprocessor">#define</span> <span class="org-variable-name">IOCTL_SET_MSG</span> _IOW(MAJOR_NUM, 0, <span class="org-type">char</span> *)
<span class="org-comment-delimiter">/*</span>
<span class="org-comment"> * _IOR means that we're creating an ioctl command</span>
<span class="org-comment"> * _IOW means that we're creating an ioctl command</span>
<span class="org-comment"> * number for passing information from a user process</span>
<span class="org-comment"> * to the kernel module.</span>
<span class="org-comment"> *</span>
@@ -2815,7 +2815,7 @@ If you want to use ioctls in your own kernel modules, it is best to receive an o
<span class="org-comment"> * device specifics, such as ioctl numbers and the</span>
<span class="org-comment"> * major device file.</span>
<span class="org-comment"> </span><span class="org-comment-delimiter">*/</span>
<span class="org-preprocessor">#include</span> <span class="org-string">"chardev.h"</span>
<span class="org-preprocessor">#include</span> <span class="org-string">"../chardev.h"</span>
<span class="org-preprocessor">#include</span> <span class="org-string">&lt;stdio.h&gt;</span>
<span class="org-preprocessor">#include</span> <span class="org-string">&lt;stdlib.h&gt;</span>
@@ -2953,7 +2953,7 @@ The <b>init_module</b> function replaces the appropriate location in <b>sys_call
</p>
<p>
Now, if B is removed first, everything will be well&#x2014;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, <b>A_open</b>, 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>B_open</b> so that it is no longer pointing to <b>A_open</b>, so it won't restore it to <b>sys_open</b> before it is removed from memory. Unfortunately, <b>B_open</b> will still try to call <b>A_open</b> which is no longer there, so that even without removing B the system would crash.
Now, if B is removed first, everything will be well &#x2014; 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, <b>A_open</b>, 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>B_open</b> so that it is no longer pointing to <b>A_open</b>, so it won't restore it to <b>sys_open</b> before it is removed from memory. Unfortunately, <b>B_open</b> will still try to call <b>A_open</b> which is no longer there, so that even without removing B the system would crash.
</p>
<p>
@@ -3561,7 +3561,7 @@ MODULE_AUTHOR(<span class="org-string">"Peter Jay Salzman"</span>);
<span class="org-comment-delimiter">/*</span>
<span class="org-comment"> * The tty for the current task, for 2.6.6+ kernels</span>
<span class="org-comment"> </span><span class="org-comment-delimiter">*/</span>
my_tty = current-&gt;signal-&gt;tty;
my_tty = get_current_tty();;
<span class="org-preprocessor">#endif</span>
ttyops = my_tty-&gt;driver-&gt;ops;

View File

@@ -612,7 +612,7 @@ Programmers use functions they don't define all the time. A prime example of thi
Kernel modules are different here, too. In the hello world example, you might have noticed that we used a function, *printk()* but didn't include a standard I/O library. That's because modules are object files whose symbols get resolved upon insmod'ing. The definition for the symbols comes from the kernel itself; the only external functions you can use are the ones provided by the kernel. If you're curious about what symbols have been exported by your kernel, take a look at */proc/kallsyms*.
One point to keep in mind is the difference between library functions and system calls. Library functions are higher level, run completely in user space and provide a more convenient interface for the programmer to the functions that do the real work---system calls. System calls run in kernel mode on the user's behalf and are provided by the kernel itself. The library function printf() may look like a very general printing function, but all it really does is format the data into strings and write the string data using the low-level system call write(), which then sends the data to standard output.
One point to keep in mind is the difference between library functions and system calls. Library functions are higher level, run completely in user space and provide a more convenient interface for the programmer to the functions that do the real work --- system calls. System calls run in kernel mode on the user's behalf and are provided by the kernel itself. The library function printf() may look like a very general printing function, but all it really does is format the data into strings and write the string data using the low-level system call write(), which then sends the data to standard output.
Would you like to see what system calls are made by printf()? It's easy! Compile the following program:
@@ -914,7 +914,7 @@ static int device_release(struct inode *inode, struct file *file)
*/
module_put(THIS_MODULE);
return 0;
return SUCCESS;
}
/*
@@ -964,8 +964,10 @@ static ssize_t device_read(struct file *filp, /* see include/linux/fs.h */
/*
* Called when a process writes to dev file: echo "hi" > /dev/hello
*/
static ssize_t
device_write(struct file *filp, const char *buff, size_t len, loff_t * off)
static ssize_t device_write(struct file *filp,
const char *buff,
size_t len,
loff_t * off)
{
printk(KERN_ALERT "Sorry, this operation isn't supported.\n");
return -EINVAL;
@@ -1063,7 +1065,7 @@ The reason for copy_from_user or get_user is that Linux memory (on Intel archite
The only memory segment accessible to a process is its own, so when writing regular programs to run as processes, there's no need to worry about segments. When you write a kernel module, normally you want to access the kernel memory segment, which is handled automatically by the system. However, when the content of a memory buffer needs to be passed between the currently running process and the kernel, the kernel function receives a pointer to the memory buffer which is in the process segment. The put_user and get_user macros allow you to access that memory. These functions handle only one caracter, you can handle several caracters with copy_to_user and copy_from_user. As the buffer (in read or write function) is in kernel space, for write function you need to import data because it comes from user space, but not for the read function because data is already in kernel space.
#+BEGIN_SRC c
#+BEGIN_SRC c :file procfs2.c
/**
* procfs2.c - create a "file" in /proc
*
@@ -1173,7 +1175,7 @@ Another interesting point here is the module_permission function. This function
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.
#+BEGIN_SRC c
#+BEGIN_SRC c :file procfs3.c
/*
procfs3.c
*/
@@ -1298,7 +1300,7 @@ digraph seq_file {
|
Seq_file provides basic functions for file_operations, as seq_read, seq_lseek, and some others. But nothing to write in the /proc file. Of course, you can still use the same way as in the previous example.
#+BEGIN_SRC c
#+BEGIN_SRC c :file procfs4.c
/**
* procfs4.c - create a "file" in /proc
* This program uses the seq_file library to manage the /proc file.
@@ -1573,7 +1575,7 @@ If you want to use ioctls in your own kernel modules, it is best to receive an o
#include <linux/fs.h>
#include <asm/uaccess.h> /* for get_user and put_user */
#include "chardev2.h"
#include "chardev.h"
#define SUCCESS 0
#define DEVICE_NAME "char_dev"
#define BUF_LEN 80
@@ -1866,9 +1868,9 @@ void cleanup_module()
/*
* Set the message of the device driver
*/
#define IOCTL_SET_MSG _IOR(MAJOR_NUM, 0, char *)
#define IOCTL_SET_MSG _IOW(MAJOR_NUM, 0, char *)
/*
* _IOR means that we're creating an ioctl command
* _IOW means that we're creating an ioctl command
* number for passing information from a user process
* to the kernel module.
*
@@ -1911,7 +1913,7 @@ void cleanup_module()
#endif
#+END_SRC
#+BEGIN_SRC c :file ioctl.c
#+BEGIN_SRC c :file other/ioctl.c
/*
* ioctl.c - the process to use ioctl's to control the kernel module
*
@@ -1923,7 +1925,7 @@ void cleanup_module()
* device specifics, such as ioctl numbers and the
* major device file.
*/
#include "chardev.h"
#include "../chardev.h"
#include <stdio.h>
#include <stdlib.h>
@@ -2037,7 +2039,7 @@ The source code here is an example of such a kernel module. We want to "spy" on
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.
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. ;)
@@ -2504,7 +2506,7 @@ void cleanup_module()
}
#+END_SRC
#+BEGIN_SRC c :file cat_noblock.c
#+BEGIN_SRC c :file other/cat_noblock.c
/* cat_noblock.c - open a file and display its contents, but exit rather than
* wait for input */
/* Copyright (C) 1998 by Ori Pomerantz */
@@ -2611,7 +2613,7 @@ static void print_string(char *str)
/*
* The tty for the current task, for 2.6.6+ kernels
*/
my_tty = current->signal->tty;
my_tty = get_current_tty();
#endif
ttyops = my_tty->driver->ops;

View File

@@ -14,7 +14,7 @@ obj-m += hello-sysfs.o
obj-m += sleep.o
obj-m += print_string.o
obj-m += kbleds.o
obj-m += file_sched.o
obj-m += sched.o
obj-m += chardev2.o
obj-m += syscall.o

View File

@@ -108,7 +108,7 @@ static int device_release(struct inode *inode, struct file *file)
*/
module_put(THIS_MODULE);
return 0;
return SUCCESS;
}
/*
@@ -158,8 +158,10 @@ static ssize_t device_read(struct file *filp, /* see include/linux/fs.h */
/*
* Called when a process writes to dev file: echo "hi" > /dev/hello
*/
static ssize_t
device_write(struct file *filp, const char *buff, size_t len, loff_t * off)
static ssize_t device_write(struct file *filp,
const char *buff,
size_t len,
loff_t * off)
{
printk(KERN_ALERT "Sorry, this operation isn't supported.\n");
return -EINVAL;

View File

@@ -21,9 +21,9 @@
/*
* Set the message of the device driver
*/
#define IOCTL_SET_MSG _IOR(MAJOR_NUM, 0, char *)
#define IOCTL_SET_MSG _IOW(MAJOR_NUM, 0, char *)
/*
* _IOR means that we're creating an ioctl command
* _IOW means that we're creating an ioctl command
* number for passing information from a user process
* to the kernel module.
*

113
4.9.11/examples/intrpt.c Normal file
View File

@@ -0,0 +1,113 @@
/*
* intrpt.c - An interrupt handler.
*
* Copyright (C) 2001 by Peter Jay Salzman
*/
/*
* The necessary header files
*/
/*
* Standard in kernel modules
*/
#include <linux/kernel.h> /* We're doing kernel work */
#include <linux/module.h> /* Specifically, a module */
#include <linux/sched.h>
#include <linux/workqueue.h>
#include <linux/interrupt.h> /* We want an interrupt */
#include <asm/io.h>
#define MY_WORK_QUEUE_NAME "WQsched.c"
static struct workqueue_struct *my_workqueue;
/*
* This will get called by the kernel as soon as it's safe
* to do everything normally allowed by kernel modules.
*/
static void got_char(void *scancode)
{
printk(KERN_INFO "Scan Code %x %s.\n",
(int)*((char *)scancode) & 0x7F,
*((char *)scancode) & 0x80 ? "Released" : "Pressed");
}
/*
* This function services keyboard interrupts. It reads the relevant
* information from the keyboard and then puts the non time critical
* part into the work queue. This will be run when the kernel considers it safe.
*/
irqreturn_t irq_handler(int irq, void *dev_id, struct pt_regs *regs)
{
/*
* This variables are static because they need to be
* accessible (through pointers) to the bottom half routine.
*/
static int initialised = 0;
static unsigned char scancode;
static struct work_struct task;
unsigned char status;
/*
* Read keyboard status
*/
status = inb(0x64);
scancode = inb(0x60);
if (initialised == 0) {
INIT_WORK(&task, got_char, &scancode);
initialised = 1;
} else {
PREPARE_WORK(&task, got_char, &scancode);
}
queue_work(my_workqueue, &task);
return IRQ_HANDLED;
}
/*
* Initialize the module - register the IRQ handler
*/
int init_module()
{
my_workqueue = create_workqueue(MY_WORK_QUEUE_NAME);
/*
* Since the keyboard handler won't co-exist with another handler,
* such as us, we have to disable it (free its IRQ) before we do
* anything. Since we don't know where it is, there's no way to
* reinstate it later - so the computer will have to be rebooted
* when we're done.
*/
free_irq(1, NULL);
/*
* Request IRQ 1, the keyboard IRQ, to go to our irq_handler.
* SA_SHIRQ means we're willing to have othe handlers on this IRQ.
* SA_INTERRUPT can be used to make the handler into a fast interrupt.
*/
return request_irq(1, /* The number of the keyboard IRQ on PCs */
irq_handler, /* our handler */
SA_SHIRQ, "test_keyboard_irq_handler",
(void *)(irq_handler));
}
/*
* Cleanup
*/
void cleanup_module()
{
/*
* This is only here for completeness. It's totally irrelevant, since
* we don't have a way to restore the normal keyboard interrupt so the
* computer is completely useless and has to be rebooted.
*/
free_irq(1, NULL);
}
/*
* some work_queue related functions are just available to GPL licensed Modules
*/
MODULE_LICENSE("GPL");

View File

@@ -30,7 +30,7 @@ static void print_string(char *str)
/*
* The tty for the current task, for 2.6.6+ kernels
*/
my_tty = current->signal->tty;
my_tty = get_current_tty();
#endif
ttyops = my_tty->driver->ops;