64-bit kernel module crashing when called by 32-bit client - linux

I've written a 64-bit kernel module that works fine for 64-bit apps, but crashes for 32-bit apps. I need to figure out how how to make the module detect if a client is a 32-bit app, and, if so manage the conversion between the 32-bit struct and 64-bit struct in my module so the system calls work.
When the module is used by a 32-bit app, the recvmsg() function crashes if the msg has cmsghdrs, because the cmsghdr struct has different size in a 32-bit app.
My module doesn't provide a 32-bit compatibility layer explicitly, even though the kernel is configured to support 32-bit applications in compatibility mode.
The module implements a new protocol, defines struct proto_ops, but I don't see compat_recv in the proto ops.
The module acts as a proxy between the client and another application (64-bit), wherein it fetches responses to client requests from the backend using netlink messages as opposed to making __sys_socket*() calls.

compat_recv is not needed in proto_ops. 32 bit userspace call to recvmsg in 64 bit kernel should go through compat_sys_recvmsg, which set MSG_CMSG_COMPAT flag. That flag makes ___sys_recvmsg() do necessary conversions before doing callback to your proto_ops and before returning to userspace.
References (in kernel tree):
Compatibility System Calls (Generic) chapter of: /Documentation/adding-syscalls.txt
/net/compat.c
/net/socket.c
Regards,
Mateusz.

Related

Bios Interrupts in assembly language

How to call interrupt in assembly language using NASM on 32 bit architecture. I try many time but result not desired.
On Linux "core dump error" and on Windows nothing happens on CMD. I read some deep that in 32 bit user application are run under ring 3 level and kernel and driver are run in ring 1. How can I do that in user level?
I follow someone on YouTube he work very well on Visual Studio with C++ or C (with inline and external assembly file ) but when I call any interrupt in external file or inline, Visual Studio says memory location violation error.
Intel 32 bit architecture (Ring level).
You can't use BIOS (or DOS) interrupts under an OS like Linux or Windows. Use system calls (Linux) or WinAPI library calls (Windows).
There is no portable ABI for interacting with the system outside your own process in assembly that works under both Linux and Windows; MacOS is also incompatible.
To use a BIOS interrupt:
make sure the BIOS exists and all of the state it depends on hasn't been modified. If the computer booted with UEFI then BIOS doesn't exist. If an OS has started it's would've nuked the state (e.g. PIC chip config, PIT config, PCI configuration space, BIOS data area, IVT, ...) that the BIOS depends on.
make sure you're in real mode or similar. If your code is 32-bit then you need to switch back to real mode, or setup a virtual8086 task (and its monitor), or use some sort of emulator (e.g. to interpret the BIOS's code instead of executing it directly).
Note that there are some special cases (e.g. the old "Advanced Power Management" API that was superseded by ACPI, the VESA BIOS Extensions) where a protected mode interface is provided as an (sometimes optional) alternative. These are mostly painful (e.g. involve setting up special descriptors for "16-bit protected mode" and copying binary blobs into them) and almost never worth the hassle.

Using GDi drawing with both 32 & 64 bit applications

Can a COM 32 bit out of process server be used for GDI drawing on a 64 bit process?
Yes it can. For GDI object HANDLEs and window HANDLES, it's guaranteed that only the low 32-bits will be used in 64-bit mode, so it should be safe to pass these between 32-bit and 64-bit. Of course, the COM server must be out of process.
Quoting from this page
On 64-bit Windows, an out-of-process 32-bit COM server can communicate with a 64-bit client, and an out-of-process 64-bit COM server can communicate with a 32-bit client. Therefore, if you have a 32-bit DLL that is not COM-aware, you can wrap it in an out-of-process COM server and use COM to marshal calls to and from a 64-bit process.
Similarly, from this page
64-bit versions of Windows use 32-bit handles for interoperability. When sharing a handle between 32-bit and 64-bit applications, only the lower 32 bits are significant, so it is safe to truncate the handle (when passing it from 64-bit to 32-bit) or sign-extend the handle (when passing it from 32-bit to 64-bit). Handles that can be shared include handles to user objects such as windows (HWND), handles to GDI objects such as pens and brushes (HBRUSH and HPEN), and handles to named objects such as mutexes, semaphores, and file handles.

SDT Kernel mode hooking

I am doing an experiment to successfully hook an API call globally, and I read somewhere about the SDT (Service Descriptor Table) and kernel mode drivers.
Does this sort of hook work for calls that reside within user32.dll and the like?
This will hook everything that need to go kernel-mode to run(I/O, FileSystem, Process/Thread, Kernel Objects).
Although they are very unstable and should not be used. You can only do SDT hooking on x86 systems version as on x64 the KeServiceDescriptorTable symbol is not exported by ntoskrnl and PatchGuard will finalize your system in a bug-check BSOD.
There are many ways to bypass KPP but I don't recommend you to proceed with this.

Application hooking :: x64 system

Is there some kind of secret to hooking both 64bit & 32bit process on a 64bit system?
In an application that I'm currently writing I need to be able to hook 64bit processes. Hooking 32bit processes works just fine on 64 & 32bit systems but, no messages are received when trying to hook 64bit applications.
Before anyone tells me that I shouldn't be doing something like this let me explain that this is a very necessary thing for me to do.. Without setting global system hooks my application would be useless/pointless.
This application is written in C#/WPF but, using a C++ dll to do the actual hooking. I've tried compiling the dll for 64bit systems although it still isn't doing what it's supposed to do. When compiled for and running on 32bit systems it works exactly as it should.
*Edit:: I am talking about hooking window messages - WH_CBT & WH_SHELL messages
In order to hook both 32-bit and 64-bit processes you need to make sure that:
You have 32-bit DLL to hook 32-bit processes and 64-bit DLL to hook 64-bit processes
SetWindowsHookEx() is invoked from 32-bit code to hook 32-bit processes and from 64-bit code to hook 64-bit processes.
The latter basically means that you have to create both 32-bit and 64-bit executable that both call SetWindowsHookEx(), providing 32-bit and 64-bit DLL respectively as an hMod parameter.
If you application is 32-bit, you will have to spawn 64-bit process that will call SetWindowsHookEx() and probably do nothing else until you unhook. Note that Windows will automatically unset hook when/if this process exits/terminates, so it has to remain alive all the time you need the hooks, probably, the whole lifetime you your application - in this case you can make your 64-bit process WaitForSingleObject() until your main application process exits/terminates and unhook and exit after WaitForSingleObject() completes.

Using a 64 bit driver in a 32 bit program. Windows

This is only a half-way programming question. First of all I have a PCI-Express card and 32/64 bit drivers. The target operating system has to be a Windows 64 bit system. I read that under Vista64 all drivers have to be certified 64 bit drivers. Is this a general restriction under 64 bit operating systems and does this also apply to "XP 64" or any Linux system?
So for simplicity let's say I use a 64 bit driver for my PCIe card under Vista64 and have a bunch of 64 bit DLLs to use the cards functionality. On the other side there's a large, legacy 32 bit exe program which needs to use the PCIe device. Converting the program to 64 bit would be a really huge effort.
So what can be done to bring that 32 bit program and the 64 bit driver together? I read that mixing 32/64 bit binaries and DLLs is not possible at all but this is hard to believe for me. I'm sure you can print out a document under Vista64 from within a 32 bit app and Windows will somehow wrap this around to a 64 bit printer driver.
64-bit certification is only required under Vista; there is no certifying authority for non-Windows platforms, and I don't believe that XP or Windows Server checks for certification (not sure though, and it may depend on which service pack you're on).
If you're using the driver via the Windows API, then there shouldn't be any problem; Windows will do the 32<->64-bit translations in the kernel. If you're trying to load the driver inside your own process, that probably won't be possible. As Dirk says you'll have to run it inside its own process and communicate through a COM server. I'm not sure what hoops you'll have to jump through if you have to run your driver in a higher-privilege execution level and want to make calls to it from user mode.
Hopefully your 64-bit DLLs offer a 32-bit API, or Windows offers a standard driver interface (if it's a common I/O device like a display or network card).
Does your 32-bit application directly call the driver? (I'm guessing a simulator for the driver!)
The only way to communicate between 32-bit and 64-bit dlls is to write a COM server that manages the communication (read: wrap EITHER the applications calls OR the 64-bit driver responses) in between.
One thing that came back to bite me: When I first wrote this COM server (yes, I too had to bear many sleepless nights before I came to know of this trick) I only built the 32-bit version of the (auto-generated) proxy/stub dll. Another bout of sleepless nights ensued before I came to know of the solution: Build the proxy/stub dll for both 32-bit and 64-bit. The 32-bit side deals with the 32-bit side (in your case the application) and the 64-bit with the 64-bit side (the driver). COM manages how the differnt versions of the proxy/stub talk to each other. And oh, do get the server registered on your system. Easy, right?
I think the whole point of a driver is to abstract away the actually workings of the hardware and present a common interface to the software. In this case, the PCIe driver needs to be 64-bit so that it can act as a go-between for Windows and the hardware, but I would think that a 32-bit application could then access the device without any troubles at all.
What's meant by that incompatibility you read about is that 32 and 64-bit assemblies can't be part of the same application - an application has to target either one or the other, though 32-bit application will generally run fine on Windows x64 using WoW64, which just acts as a translator.
Are you currently experiencing problems, or are you just asking hypothetically?

Resources