Irfan’s Corner on the Web On Mac, Linux, Grid, Virtualization and Software Technology

30Jan/080

Strange Sound switching problem and soluton

 
I've had this problem once before, I think in OpenSUSE 10.3, now in Debian I'm getting it again: On my Dell Inpsiron 6400 Laptop, when I plug in any pair of headphones, the sound does not switch from the laptop speakers to the headphones, rather the sound continues to play from the laptop speakers.This is a very annoying problem. But despair not, I have a workaround. Whenever you want to use headphones, simply kill all sound applications, and unload the snd_hda_intel module (In case you use Intel HDDA Sound). Plug in your headphone, and load the snd_hda_intel module again via modprobe. Thats it! Now your sound should be coming through the headphones. Now even if you unplug your headphones, you will not hear sound from the speakers, rather you have to unload and modprobe snd_hda_intel again to get sound from the speakers.Whats strange is that I did not have this problem a few weeks ago on the same Linux installation. But anyway now that I have a work around it doesn't matter. Its always fun to load/unload modules :D .
30Jan/074

VMWare, openSUSE and USB Ports!

I finally decided to take the plunge and remove Windows XP completely from my notebook (so far I was dual-booting), however I require certain applications which I need to use as part of my research that's why I have installed VMWare and hosted Windows XP on it, with the software. I'm so far very impressed by the performance, although I only have 512MB RAM, but it doesn't feel as if I'm running an emulated environment. VMWare allows me to stay in Linux and access those application which I require which are not available on Linux yet. Gradually I think virtualization will facilitate Linux in taking over the Desktop J.

However I have come across a problem which has been purely setup by open source "fundamentalists"! As soon as I installed VMWare I tried out various hardware including USB flash drives and USB camera, but they won't work? And upon investigation it was revealed that this was due to a method for accessing the USB port, which was claimed to be insecure, hence support for it was discontinued in openSUSE 10.2, in a heated discussion in the forums, it was very clear who was behind all this, a respected kernel hacker. Greg KH recently jumped the canon and was the one who posted a patch to the LKML, for eliminating binary drivers. I respect him; however he does not seem to have any for users. In a post he said:

"We are not supporting VMWare, because it is closed source and proprietary"

It indeed is, but is there any other open source solution that beats it? Xen requires kernel modification and hence does not work with Windows, the only solution to virtualize windows on Linux computer right now (KVM may change that in future, however it is in the initial stages of development, and runs only on the latest processors) is to use VMWare. In effect VMware is doing us a favour by porting VMWare to Linux at all! I'm 100% certain that the openSuse 10.2 kernel team is doing the right thing by closing a potential exploitable thing, however the approach they have adopted is completely unacceptable! If the concerned methods is indeed exploitable, it is only in the application developers own interest to adopt a more secure method for accessing USB ports, however why can't all Linux distributions follow the same standard then? I can well imagine why VMWare didn't use the openSuse method of 'securely' accessing USB ports, because it would conflict with other popular distributions and if they try to support each method, would result in excessive workload to the company. The best method in this case would be to use something like the OSDL (what's the job of OSDL anyway?) to provide recommendations to the linux distributions in order to standardize kernel level interfaces, so that application developers do not end up supporting dozens of methods for a trivial task as accessing a USB port.

For the time being while Windows runs on more than 90% of the worlds desktops, and is a lucrative market for Independent Software Vendors, we can not ignore users who have applications which are Windows dependant; there are 1,000 times more such applications than Linux dependant apps. And the only way to allows users to run those applications on Linux for the time being is to use virtualization (WINE in my opinion, is progressing nicely, but still has some way to go).

PS. Instead of just ranting here, I will be releasing an openSUSE default kernel with the USB access feature turned on, so that people who need it now can use it

1Oct/060

Adding a System call (linux 2.4.x)

1. About This Document

This document explains a way to add a system call to linux kernel catered to the linux 2.4.x series. It is based on the guide by Worcester Polytechnic Institute available at here. The guide is for linux 2.2.x, some changes where to the cotents to make it a guide for linux 2.4.x. The reference kernel in this guide is linux 2.4.31

A system call is the standard way an OS service is exported to a user program. For example, to provide users a new semaphore like synchronization method, some system calls need to be provided to access it. Likewise, a system call may be used to give users access to internal information of a file system such as superblock or inodes. The following description is based on linux kernel version 2.2.14 on i386 machine architecture. Also, it is assumed that readers are familiar with Building Linux Kernel.

2. Preparing for A New System Call

A system call cannot be called directly from a user process. Instead, they are called indirectly via an interrupt and looked up in an interrupt table. Thus, when you define a new system call you insert a new entry in this table. You do this by editing the file linux/arch/i386/kernel/entry.S. Inside, you should see lines like:


.data
ENTRY(sys_call_table)
.long SYMBOL_NAME(sys_ni_syscall) /* 0 - old "setup()" system call*/
.long SYMBOL_NAME(sys_exit)
.long SYMBOL_NAME(sys_fork)
.long SYMBOL_NAME(sys_read)
.long SYMBOL_NAME(sys_write)
..
..
.long SYMBOL_NAME(sys_ni_syscall) /* sys_set_tid_address* /

After the "sys_ni_syscall" line, add your entries for your new system calls, with the words "sys_" prepended. For example, you might add the following line for your new system call "myservice":


.long SYMBOL_NAME(sys_myservice) /*259 */

You also need to generate a system call "stub" so that an ordinary user program can invoke your system call. You do this by editing the file linux/include/asm/unistd.h (In linux sources) where you will find lines like:


#define __NR_exit 1
#define __NR_fork 2
...
#define __NR_exit_group 252

You should add #defines for your new system calls at the end, with the prefix "__NR_" in front of it. For example, you might add the line:


#define __NR_myservice 259

3. Places for Your System Call Source Files

After inserting your new system call entry in the interrupt table and preparing a stub for it, you will need to define (or implement) the system call. It will be easiest to have the system call definitions in your own source code files, say myservice.h and myservice.c.

In general, header files for machine architecture independent system calls and functions are kept under linux/include/linux/ and machine architecture dependent ones are kept in linux/include/asm/. Therefore, it would be a good idea to follow this convention. For example, the header file for the system calls for your new synchronization method, of which the implementation is machine architecture specific, would be placed in linux/include/asm/, while the header file for your machine architecture independent system call that access the superblock of one or more of your file systems would be placed under linux/include/linux.

The place for actual implementation file (myservice.c in this example) could vary. For example, if you are implementing a new process synchronization method, linux/ipc/ would be the best place for it. If you are implementing a file system related one, linux/fs/ would be the best place.

Remember that you will need to modify the Makefile in the directory you placed your .c file so that your code gets compiled and linked in properly. Modify the Makefile line to have a .o of your source code. For example, adding myservice.o in linux-2.4.31/mm/


obj-y := memory.o mmap.o filemap.o mprotect.o mlock.o mremap.o vmalloc.o slab.o bootmem.o swap.o vmscan.o page_io.o page_alloc.o swap_state.o swapfile.o numa.o oom_kill.o shmem.o myservice.o

The rest of the Makefiles can remain untouched (Makefile changes will be similar if you choose to add your code elsewhere).

4. System Call Source File Basics

In order to be linked properly, your system calls need the word "asmlinkage" prepended to their function header and "sys_" prepended to the name. For example, you would have:


asmlinkage int sys_myservice(int arg1, char* arg2) {
/* implementation of myservice */
}

Also, you will have to have #include so the compiler will recognize the word "asmlinkage".

Lastly, the user "stub" can be automatically generated so that a user program can use your system call. There are some macros defined for this in . The format is "_syscallN(return type, function name, arg1 type, arg1 name ...)" where "N" is the number of parameters. For example, you might have the line:


_syscall2(int, myservice, int, arg1, char*, arg2);

to generate the stub (in this case, the 2 is for 2 arguments). Note, that your call to generate the stub (as above) should be put it in your header file for users(myservice-user.h). Also, you need to #include in myservice-user.h to make this work. A user program could then just call myservice() as they do other system calls.

Here is an example myservice.h, myservice.c, myservice-user.h and user-app.c assuming myservice.h is under linux/include/linux/ and myservice-user.h is under /usr/include/sys/

myservice.h (used within kernel only)

#ifndef __LINUX_MYSERVICE_H
#define __LINUX_MYSERVICE_H#include

#endif

myservice.c (system call implementation)

include
asmlinkage int sys_myservice (int arg1, char* arg2) {printk("My Service Called");
return(1);
}
myservice-user.h (for user application)

#include
#include_syscall2(int, myservice, int, arg1, char*, arg2);
user-app.c (user application)

#include
main() {myservice(1, "hi");