Linux Kernel 5.0.0-37
I'm writing a function to manage permissions to be provided as a function pointer to the struct inode_operations. Here is a simplified stub implementation:
#include <linux/cred.h>
int pfsw_permission(struct inode *ino, int op){
if(uid_eq(INIT_USER->uid, get_current_user()->uid)){
printk(KERN_INFO "Current user is root\n");
} else {
printk(KERN_INFO "Current user is not root\n");
}
if(op & (MAY_READ | MAY_WRITE)){
return 0;
}
return -EACCES;
}
when compiling a kernel module containing this function and trying to load it dmesg shows the following error:
Unknown symbol root_user (err -2)
This I think is due to INIT_USER macro coming from include/linux/sched/user.h which is defined as
extern struct user_struct root_user;
#define INIT_USER (&root_user)
QUESTION: Why is the symbol root_user declared, but not defined? How to use INIT_USER correctly?
root_user does not seem to be exported using EXPORT_SYMBOL by the linux kernel; therefore you cannot use it from a module.
Looking at its definition we can see that the uid value is set to GLOBAL_ROOT_UID. This is a macro defined in include/linux/uidgid.h and is basically just a type cast of 0 to kuid_t so you can use just that macro if all you need is the UID.
So ...
Why is the symbol root_user declared, but not defined?
The symbol is defined. It's not exported though so you cannot use it from a module.
How to use INIT_USER correctly?
"Not". You cannot use it.
Related
I have a 218KB .dll and a 596KB .so file, both with identical names. I want to link to the .dll to avoid the "unresolved external symbol" error that the linker returns, but I can't find a way to link to the DLL file.
According to this Pelles C forum topic, I need to use the .def file to create a .lib... but I don't have a .def file. This forum topic shows how to use polink to create a .lib from the command line, so I ran polink /? to get some more options. I noticed a /MAKEDEF option, but running this with both the .dll and the .so gives a "No library file specified" fatal error.
I have been trying to do this for three hours, and am out of ideas. I have got to the point where my web searches turn up my own help-requests. There must be a way to do this... How can I link to a .dll?
With information found in the header #include and your details, here is a way to replace the missing function by calling them dynamically from your software.
1- the following prototype is in #include :
typedef float (* XPLMFlightLoop_f)(float inElapsedSinceLastCall, float inElapsedTimeSinceLastFlightLoop, int inCounter, void * inRefcon);
2- some const that you can fill as needed:
const char *sDllPathName = "<Your XPLM_API DLL>.dll";
const char *sXPLMRegisterFlightLoopCallbackName = "XPLMRegisterFlightLoopCallback";
In order to confirm the sXPLMRegisterFlightLoopCallbackName, you can
use the freeware Dependency Walker and check name and format of
the exported functions.
3- declare the prototype of the external function:
Be aware to the calling convention __cdecl or __stdcall
In the current case, the keyword XPLM_API is defined in the XPLMDefs.h as follow:
#define XPLM_API __declspec(dllexport) // meaning __cdecl calling convention
typedef void (__cdecl *XPLMRegisterFlightLoopCallback_PROC)(XPLMFlightLoop_f, float, void *);
4- clone the function to call it in your software:
#include <windows.h>
void XPLMRegisterFlightLoopCallback(XPLMFlightLoop_f inFlightLoop, float inInterval, void * inRefcon)
{
HINSTANCE hInstDLL;
XPLMRegisterFlightLoopCallback_PROC pMyDynamicProc = NULL;
// Load your DLL in memory
hInstDLL = LoadLibrary(sDllPathName);
if (hInstDLL!=NULL)
{
// Search for the XPLM Function
pMyDynamicProc = (XPLMRegisterFlightLoopCallback_PROC) GetProcAddress(hInstDLL, sXPLMRegisterFlightLoopCallbackName);
if (pMyDynamicProc != NULL)
{
// Call the XPLM Function with the orignal parameter
(pMyDynamicProc)(inFlightLoop,inInterval,inRefcon);
return;
}
}
// Do something when DLL is missing or function not found
}
5- just add your described call:
...
XPLMRegisterFlightLoopCallback(callbackfunction, 0, NULL);
...
How can I find the library where the function open() is? Like, the name of the actual "xxxxxx.so" file that contains that function? Also, is there a place I could typically get this information for other functions?
I didn't know how to find the library a given function was in, which
was required for dlopen
Knowing the library is not required for dlopen():
If file is a null pointer, dlopen() shall return a
global symbol table handle for the currently running process image.
This symbol table handle shall provide access to the symbols from an
ordered set of executable object files consisting of the original
program image file, any executable object files loaded at program
start-up as specified by that process file (for example, shared
libraries), and the set of executable object files loaded using
dlopen() operations with the RTLD_GLOBAL flag. …
But if you really want to know:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
int main()
{
// We don't need to know the library for dlopen():
void *handle = dlopen(NULL, RTLD_NOW);
if (!handle) puts(dlerror()), exit(1);
void *p = dlsym(handle, "open");
char *s = dlerror();
if (s) puts(s), exit(1);
printf("open = %p\n", p);
// But we can find the library with a Glibc extension:
Dl_info info;
if (dladdr(p, &info))
printf("%s contains %s\n", info.dli_fname, info.dli_sname);
}
I have a main application which dynamically loads a dylib, from inside that dylib I would like to call exported functions from my main program. I'm using dlopen(NULL,flag) to retrieve my main applications handle and dlsym(handle, symbol) to get the function.
dlopen gives no error but when I try to dlsym my function I get the following error:
dlerror dlsym(RTLD_NEXT, CallMe): symbol not found
The symbol is exported corrected confirmed by nm
I'm not sure why RTLD_NEXT is there? is this the result of dlopen(NULL,flag)?
How can I solve this problem or achieve my goal?
Or are there other ways to call the main application (preferably not by passing on function pointers to the dylib)?
Thanks in advance!
Added:
Export:
extern "C" {
void CallMe(char* test);
}
__attribute__((visibility("default")))
void CallMe(char* test)
{
NSLog(#"CallMe with: %s",test);
}
Result of nm
...
0000000000001922 T _CallMe
..
Code in dylib:
void * m_Handle;
typedef void CallMe(char* test);
CallMe* m_Function;
m_Handle = dlopen(NULL,RTLD_LAZY); //Also tried RTLD_NOW|RTLD_GLOBAL
if(!m_Handle)
return EC_ERROR;
m_Function = (CallMe*)dlsym(m_Handle, "CallMe");
if(!m_Function)
return EC_ERROR;
m_Function("Hallo");
I think a better approach might be to establish a proprietary protocol with your dynamic library where you initialise it by passing it a struct of function pointers. The dynamic library needs to simply provide some sort of init(const struct *myfuncs), or some such, function and this makes it simpler to implement the dynamic library.
This would also make the implementation more portable.
I'm trying to use gate_desc *idt_table in a kernel module. The set_trap_gate() function defined in desc.h uses this pointer. In desc.h is also a definition : extern gate_desc idt_table[].
I tried different things:
use idt_table in my module without definition or affectation
affect idt_table with my (valid) idt_table address
I get either an id_table undefined warning during compilation or incomplete type for idt_table.
creating a new var named for instance gate_desc *it = (gate_desc *)#; And copy the set_trap_gate, set_gate, write_idt_entry, pack_gate functions from sched.h to my module file (renaming them, and using it instead of idt_table). This compiles fine but when inserting my module I get an unknown symbol in module (ret -1) error.
(there is no reference in my module to idt_table, and the functions I use from sched do use my variable).
I tried to see where in the files included by sched.h was defined idt_table, but couldn't find it!
Does someone know how I could use, the idt_table pointer from sched.h (affecting it with the corrct address) or create a new pointer?
Theoretically, you could implement a non-init-section set_trap_gate() via:
void set_trap_gate(int n, void *addr)
{
struct { uint16_t lim; struct desc_struct *idt_table; }
__attribute__((packed)) idt;
__asm__ ("sidt %0" : : "m"(idt) : "memory");
_set_gate(idt.idt_table + n, 15, 0, addr);
}
But that'd be CPU-local, i.e. it's not guaranteed to modify any other IDT but the one of the CPU it's running on. Also, it might fall foul of writeprotected memory.
What exactly is it you're trying to achieve ?
I'm using Dev-C++ 4.9.9.2 with MinGW to compile this code:
/* get the information about the group. */
struct group* group_info = getgrnam("PLACEHOLDER");
/* make sure this group actually exists. */
if (!group_info) {
printf("group 'PLACEHOLDER' does not exist.\n");
}
else
{
char** p_member;
printf("Here are the members of group 'PLACEHOLDER':\n");
for (p_member = group_info->gr_mem; *p_member; p_member++)
printf(" %s\n", *p_member);
}
}
I included the following header files:
grp.h
sys/types.h
(got them from glibc 2.13 (maybe this is wrong, but a friend told me this is the right way))
when I try to compile the code, i get a bunch of errors in the headers from glibc, like:
12 C:\glibc-2.9\include\sys\cdefs.h expected constructor, destructor, or type conversion before '(' token
12 C:\glibc-2.9\include\sys\cdefs.h expected `,' or `;' before '(' token
4 C:\glibc-2.9\include\grp.h expected constructor, destructor, or type conversion before '(' token
Edit:
This is the whole Code
#include <grp.h> /* defines 'struct group', and getgrnam(). */
#include <sys/types.h> /* defines 'gid_t', etc. */
BOOL getListOfGroupMembers() {
/* get the information about the "strange" group. */
struct group* group_info = getgrnam("PLACEHOLDER");
/* make sure this group actually exists. */
if (!group_info) {
printf("group 'PLACEHOLDER' does not exist.\n");
}
else
{
char** p_member;
printf("Here are the members of group 'PLACEHOLDER':\n");
for (p_member = group_info->gr_mem; *p_member; p_member++)
{
printf(" %s\n", *p_member);
}
}
return 0;
}
The bool return doesn't make sense at the moment, I want to change that when compiling works.
You can't just bring over a couple of header files from glibc over to mingw on windows. These header files are not self contained, they need a lot of other header files, and probably might even need to be installed on a system (not just refered to in the glibc source folders..)
Besides that, glibc isn't made for windows - these header files are crafted specifically for glibc, and win32 doesn't have the getgrnam() function anyway. (You'd need cygwin, which has its own header files)
There is a missing brace in the lowest for-loop, but maybe it is just a posting error?
I doubt this is the source of the problem, but it looks like your for has a closing bracket }, but lacks and opening one.