Creating a device-file node An introduction to some privileged upcoming programming exercise)

advertisement
Creating a device-file node
An introduction to some privileged
Linux system-calls (needed for an
upcoming programming exercise)
A device-driver example
• We want to build a simple device-driver,
one that would let ordinary applications
read and/or write to the CMOS memory
(e.g. to adjust the date or time-of-day)
• This will require that we have a so-called
device ‘special’ file in the ‘/dev’ directory
• Creating such a file normally requires the
privileges of a System Administrator – but
could be accomplished via a suitable LKM
The Linux commands
• If a System Administrator wanted to setup
a device-file in the ‘/dev’ directory named
‘cmos’ that has read-and-write privileges,
the following commands would be used:
root# mknod /dev/cmos c 70 0
root# chmod a+rw /dev/cmos
• Here the ‘c’ argument indicates that the
file-node is for a ‘character-mode’ device
• Values 70 and 0 are arbitrary id-numbers
Removing a device-file
• To delete a file from the ‘/dev’ directory, the
SysAdmin uses the ‘unlink’ command:
root# unlink /dev/cmos
• Because of standard privilege-restrictions
on the ‘/dev’ directory, these commands
will fail if executed by unprivileged users
• Students have not been given sufficient
privileges to successfully execute these
‘mknod’, ‘chmod’ and ‘unlink’ commands
LKM’s have full privileges
• But CS students in this class DO possess
privileges that allow them to install, and to
remove, Linux kernel modules:
user$ /sbin/insmod cmos.ko
user$ /sbin/rmmod cmos.ko
• While installed, modules execute inside
the kernel itself, with no privilege barriers
• Hence we should be able to perform the
steps necessary to create a device-file!
Developers disapprove!
• The Linux developers want a ‘secure’ OS,
so they have not made it convenient for us
to create modules that would bypass the
expected privilege-restrictions
• For example, they use ‘information hiding’
capabilities of the GNU “C” compiler to
conceal the locations of kernel-code that
performs ‘mknod’, ‘chmod’, and ‘unlink’
‘Open Source’ philosophy
• At the same time, the Linux developers do
adhere to the ‘Open Source’ philosophy –
the kernel’s source-files are available in a
tree-structured sub-directory:
$ cd /usr/src/linux
• The protocol for invoking system-services
is widely known, and the ID-numbers for
system-calls are in this header-file:
$ cat include/asm/unistd.h
How to invoke ‘unlink’
• This in-line assembly language code, used
within an LKM, can ‘unlink’ a device-file:
#include <asm/uaccess.h>
char pathname[] = “/dev/cmos”;
int retval;
// for get_fs(), set_ds()
// pathname for file to be ‘unlinked’
// for the system-call’s return-value
{
set_fs( get_ds() );
// allow kernel to address our data
asm(“ pushal
“); // preserve registers
asm(“ mov $10, %eax
“); // ID for ‘sys_unlink()’
asm(“ mov $pathname, %ebx “); // address of pathname
asm(“ int
$0x80
“); // invoke kernel service
asm(“ mov %eax, retval
“); // save the return-value
asm(“ popal
“); // recover registers
}
How to invoke ‘mknod’
#include <asm/uaccess.h>
char pathname[] = “/dev/cmos”;
int retval;
// for get_fs(), set_ds()
// pathname for file to be ‘unlinked’
// for the system-call’s return-value
{
set_fs( get_ds() );
// allow kernel to address our data
asm(“ pushal
“); // preserve registers
asm(“ mov $14, %eax
“); // ID for ‘sys_mknod()’
asm(“ mov $pathname, %ebx “); // address of pathname
asm(“ mov $020000, %ecx
“); // S_IFCHR constant
asm(“ mov $70, %edx
“); // our driver ID-number
asm(“ shl $8, %edx
“); // DH=major, DL=minor
asm(“ int
$0x80
“); // invoke kernel service
asm(“ mov %eax, retval
“); // save the return-value
asm(“ popal
“); // recover registers
}
How to invoke ‘chmod’
#include <asm/uaccess.h>
char pathname[] = “/dev/cmos”;
int retval;
// for get_fs(), set_ds()
// pathname for file to be ‘unlinked’
// for the system-call’s return-value
{
set_fs( get_ds() );
// allow kernel to address our data
asm(“ pushal
“); // preserve registers
asm(“ mov $15, %eax
“); // ID for ‘sys_chmod()’
asm(“ mov $pathname, %ebx “); // address of pathname
asm(“ mov $000666, %ecx
“); // read-and-write by all
asm(“ int
$0x80
“); // invoke kernel service
asm(“ mov %eax, retval
“); // save the return-value
asm(“ popal
“); // recover registers
}
Use ‘man’ for prototypes
• Many of the Linux system-calls use the
names of standard library-functions and
employ the same function-arguments
• So the ‘man’ page for the library-function
will often give the system-call’s prototype
• Example:
$ man 2 mknod
• (You need the ‘2’ here -- or you’ll get the
manual-page for the ‘mknod’ command)
Parameter-passing rule
• Assembly language code that invokes a
system-call always uses register EAX to
pass the system-call’s ID-number
• The system-call’s parameters (up to five)
are then passed to the kernel in these
registers (and in this order):
EBX, ECX, EDX, ESI, EDI
• Obviously this rule would only apply to a
Linux version for the 32-bit x86 platforms
In-class exercise #1
• Compile and install our ‘tempcdev.c’ LKM
(from the class website), then verify using
the ‘ls’ command that the ‘/dev/cmos’ file
exists (and look at its access-permissions)
• Remove that LKM, and use ‘ls’ to confirm
that the ‘/dev/cmos’ file has been deleted
• Use the ‘dmesg’ command to display the
messages in your machine’s kernel logfile
In-class exercise #2
• The file created by our ‘tempcdev.c’ LKM
has ‘read-only’ permissions. So can you
modify its ‘module_init()’ function so that
the ‘/dev/cmos’ file will get created with
both ‘read’ and ‘write’ access-privileges?
Reminder!
• Information presented in tonight’s lesson
carries with it the responsibility of ethical
behavior on your part – do not misuse it!
• You are NOT authorized to look at other
users’ files -- nor to erase or modify files
which do not belong to you
Download