Making a virtual file in Linux - linux

I'm working with some existing software that I cannot change, and it loads its config data from a bunch of config files, all following the same naming scheme - let's say, file_param1.conf, file_param2.conf, file_param3.conf etc. The difference between the content of the files is just param1 vs param2 vs param3, so a typical config file will look like
foo=bar
x=param1
or
foo=bar
x=param2
Is there any examples anywhere on creating a virtual fs in Linux that would let me on access of file_param1.conf generate the file dynamically with the appropriate param variable? I know about scriptfs but not about any tutorials on using it.

(Posting as an answer because this is too long for a comment.)
You might find it easier to use an LD_PRELOAD library and interpose on the open()/fopen()/open64() or whatever exact library call(s) your existing software uses to access your configuration file and replacing the application-supplied file name with one that points to the file you want to use.
This code is off the top of my head and I haven't tried compiling it:
#include <dlfcn.h>
// don't want to #include anything else or we're likely to get
// the vararg prototype for open()
int strcmp( const char *s1, const char *s2 );
// typedef a function pointer
typedef int ( *open_func_ptr_t )( const char *, int, mode_t );
static open_func_ptr_t real_open = NULL;
int open( const char *pathname, int flags, mode_t mode )
{
// find the real open() call
if ( real_open == NULL )
{
real_open = ( open_func_ptr_t ) dlsym( RTLD_NEXT, "open" );
}
if ( 0 == strcmp( pathname, "/path/to/config/file" );
{
pathname = "/path/to/replacement/config/file";
}
return( real_open( pathname, flags, mode ) );
}
That code relies on the fact that although open() is declared as a varargs function because of the restrictions placed on current C code, originally C didn't have prototypes so all functions were de facto vararg functions. The open() call only accesses the mode argument when needed, so open() doesn't always need to be passed a mode argument. With current C, the only way to do that is with a vararg function. That makes #include files problematic with this code as any declaration of open() will be the vararg one and that will cause the code to not compile. You might need to replace mode_t with int (or whatever it's typedef'd to) in order to compile.
Compile that with cc [-m64|-m32] -shared source.c -ldl -o mylib.so. You need the -ldl to link in dlsym(), and you need the proper -m64 or -m32 option to get a 64- or 32-bit library to match your application.
Then set LD_PRELOAD to your .so file:
LD_PRELOAD=/path/to/mylib.so
export LD_PRELOAD
Then run your application with the LD_PRELOAD set. You also need to be real careful that any child processes spawned by your application are all the same 32- or 64-bit as the shared object LD_PRELOAD is set to. If you nave mixed 32- and 64-bit processes to deal with, read the man page for ld.so and pay particular attention the the $PLATFORM section.
Note also that the code is not reentrant because of the race condition modifying real_open and might have problems with multithreaded access to open().

Related

Module Programming in linux

here is the simple module program code.
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
#include <linux/init.h> /* Needed for the macros */
static int hello3_data __initdata = 3;
static int __init hello_3_init(void)
{
printk(KERN_INFO "Hello, world %d\n", hello3_data);
return 0;
}
static void __exit hello_3_exit(void)
{
printk(KERN_INFO "Goodbye, world %d\n",hello3_data);
}
module_init(hello_3_init);
module_exit(hello_3_exit);
I've initialized a variable with __initdata macro and a function with __init. when I did insmod the module was inserted and i was able to see the log message(/var/log/messages). But, when I did rmmod it was unable to remove it, and it says Resource busy.
My question is does the `modules_init` function cleans the memory of `hello3_data`??
or it is done by `module_exit`??.
Someone please explain.
Please when declaring the varialble hello3_data you're using the __initdata modifier which specifies that the variable shall be used in only the __init function.
Try recompile your kernel module with options like make CONFIG_DEBUG_SECTION_MISMATCH=y and you shall see warnings like this:
WARNING: /home/pengyu/temp/yusen/test_mod.o(.exit.text+0x3): Section mismatch in reference from the function cleanup_module() to the variable .init.data:hello3_data
The function __exit cleanup_module() references
a variable __initdata hello3_data.
This is often seen when error handling in the exit function
uses functionality in the init path.
The fix is often to remove the __initdata annotation of
hello3_data so it may be used outside an init section.
You could simply remove __initdata and try again.
EDITED:
Here I'm trying to provide further explanations. The kernel module itself is in the format of ELF (Executable and Linkable Format) (with some kernel-module-specific sections). Feature of the .init and .fini sections is supported by the linkers and loaders including insmod.
In this case the attribute #define __initdata __section(.init.data) works like __attribute__((section(".init.data"))) which explicitly specifies which section the data/function shall be put in.
As a kernel module the section of .init is not guaranteed to be kept after module initialization, and anything inside that section is not supposed to be referenced outside the initialization function. See page 31 of Linux Device Drivers, Third Edition:
The _init token in the definition may look a little strange; it is a hint to the kernel that the given function is used only at initialization time. The module loader drops the initialization function after the module is loaded, making its memory available for other uses. There is a similar tag (_initdata)for data used only during initialization. Use of __init and __initdata is optional, but it is worth the trouble. Just be sure not to use them for any function (or data structure)you will be using after initialization completes

How to use exported symbols optionally only if they are present in an insmoded Linux Kernel module?

I am modifying a Linux Kernel to add some functionality to the Linux Virtual Server (LVS).
I developed a module (which I called net/netfilter/ipvs/ip_vs_utils.c) with some functions to be used when load-balancing. All the functions here are exported using EXPORT_SYMBOL().
This module, logically is not loaded all the time. My intention is to allow the user to decide if he want to use this additional functionality or not (loading or unloading the module).
My question is how could I invoke these functions OPTIONALLY (depending if the module is running or not) from a existing (and of course modified) module (net/netfilter/ipvs/ip_vs_core.c). Something like this:
if(ip_vs_utils_IsLoaded)
{
function1(arg1, arg2, arg3); // being function1 defined on ip_vs_utils.c
}
I think you need a trampoline always(or almost always) loaded into kernel.
In trampoline code, you need to such variables.
struct module *ip_vs_utils_mod;
EXPORT_SYMBOL(ip_vs_utils_mod);
/* function pointers */
ret_type (*ip_vs_utils_afunc_ptr)(func_arg_list); /* Add static if you put it in a header file! */
EXPORT_SYMBOL(ip_vs_utils_afunc_ptr); /* ******EXPORTED***** */
When the ip_vs_utils is loaded, you need to init all the variables, initialization code in ip_vs_utils.c:
ip_vs_utils_mod = THIS_MODULE;
/* init function pointers */
/* ip_vs_utils_afunc_impl is the real implementation
* of the function, it is *****NOT***** needed to export it
*/
ip_vs_utils_afunc_ptr = ip_vs_utils_afunc_impl;
And add the trampoline functions in trampoline code:
ret_type ip_vs_utils_afunc(func_arg_list)
{
ret_type ret = DEFAULT_RET;
if (try_module_get(ip_vs_utils_mod)) {
ret = (*ip_vs_utils_afunc_ptr)(func_arg_list);
module_put(ip_vs_utils_mod);
}
return ret;
}
try_module_get() is needed to protect the module from being suddenly unloaded while ip_vs_utils_afunc_ptr() is being invoked.
You can also use RCU instead to reduce the overhead of try_module_get()/module_put(). (But it is hard)
Or you can used some trampoline-hack like dynamic link in userspace(you may need to change a lot in the linux kernel)

Use a supplied dll in Visual C++ project

I just bought a device that comes with a dll file. I want to use Visual C++ to program the device. How do I load the .dll file into my project?
A DLL is a library file that contains compiled program logic, just like an EXE. You can't execute it alone, but like an EXE file you can't just 'load' it into your project either.
You will need to use functions like Load Library to load the library, and then GetProcAddress to find a function you want to call.
Edit:
After you clarified your question in the comments you are trying to write a windows program instead of a program you run on your device.
I wrote some sample code to show you how to start:
#include <windows.h> // This is a windows header file. The functions I mentioned above are declared here
#include "mpusbapi.h" // This is the header file supplied. It declares the function prototypes that are defined in the DLL
int main(int argc, char* argv)
{
// Try to load the library
HMODULE mpbusDLL = NULL;
mpbusDLL = LoadLibrary(L"mpusbapi.dll");
if (mpbusDLL != NULL) {
// If the library could be loaded, then load the functions using GetProcAddress()
// Load the function 'MPUSBOpen' from the DLL
MPUSBOpen = (HANDLE(*)(DWORD, PCHAR, PCHAR, DWORD, DWORD)) GetProcAddress(mpbusDLL, "_MPUSBOpen");
...
MPUSBOpen(...);
}
}
This C code will load your libary and then attempt to load the function MPUSBOpen, which is implemented in your DLL.
You will need to load the other functions defined in your header file the same way (at least if you want to use them).

Will the linker compare the access level when finding a member function at linking time?

Accidently, I encounter a linking error.
The program is somewhat like this:
//a.h
class A
{
int a;
#ifdef AAA
public:
#endif
int getA();
}
//a.cpp
include "a.h"
int A::getA()
{
return a;
}
//test.cpp
#include "a.h"
int main()
{
A a;
a.getA();
return 0;
}
These three files are in two project, a.h and a.cpp in a project A in which the AAA macro is undefined, test.cpp in a project Test in which AAA macro is defined. And project Test denpends on project A.
Then I encounter a link error. I did this test on visual studio 2008.
So my question is this:"Will the link compare the access level when finding a member function symbol at linking time?"
In my previous opinion, the access level only take effect in compilation. But in this case,
it seems that the access level may also make effect in linking time.
The linker is innocent. C++ compilers mangel names and incorporates things as access modifiers, overloads (i.e. return and argument types), template(? not quite sure) etc... in the final to produce something unambigious that also forms whatever the linker considers a valid identifier (at least [a-zA-Z_][a-zA-Z0-9_]*, as C requires no mangling). The linker only sees that mangled name, and it can't report anything except "you call this function but it's not defined anywhere". public A::getA() a different name as private A::getA().
The solution? Don't use the preprocessor for such batshit things. Or convince the VS developers to intercept such error messages and translate them into something more meanignful (but since they didn't in the past and sane code rarely encounters this problem, that's unlikely).

Stack issues when calling a DLL compiled with Visual C++ in GCC

I'm trying to call some functions in a DLL compiled with (I believe) Visual C++ from my program, which is compiled using GCC.
To call the functions in the DLL, I do a LoadLibrary() on the DLL, and then a GetProcAddress() to get the address of a particular function, which I then call. This function returns a list of pointers to the functions in the DLL I'm to call.
Well, when I try to call those functions, they don't work properly. I ran my program through a debugger, and it looks like the DLL library function is looking for one of the passed arguments at ebp+8, even though GCC has put it at ebp-24.
It looks definitely like a stack issue. What's more, when the GCC program function which calls the DLL function returns, my program crashes -- so something screwey is going on with the stack. Does anyone know what I need to do in order to fix this? I'm not able to access the DLL code.
Also: I tried putting __cdecl and __stdcall before the DLL function definition in my program's source file, but this changes nothing.
Looks like a calling convention problem. Make sure you're putting the calling convention tag in the right place. With GCC, it should look like this:
typedef int (__stdcall *MyFunctionType)(int arg1, const char *arg2);
MyFunctionType myFunction = (MyFunctionType)GetProcAddress(myModule, "MyFunction");
// check for errors...
int x = myFunction(3, "hello, world!");
[EDIT]
Looks like your problem has nothing to do with calling conventions (although getting them right is important). You're misusing BSTRs -- a BSTR is not a simple char* pointer. It's a pointer to a Unicode string (wchar_t*), and furthermore, there is a 4-byte length prefix hidden before the first characters of the string. See MSDN for full details. So, the call to SetLicense() should look like this:
BSTR User = SysAllocString(L""); // Not sure if you can use the same object here,
BSTR Key = SysAllocString(L""); // that depends on if SetLicense() modifies its
// arguments; using separate objects to be safe
// check for errors, although it's pretty unlikely
(textCapLib.sdk)->lpVtbl->SetLicense((textCapLib.sdk), User, Key);
SysFreeString(User); // Hopefully the SDK doesn't hang on to pointers to these
SysFreeString(Key); // strings; if it does, you may have to wait until later to
// free them

Resources