Undeclared ptep_t in linux_kernel system call - linux

I'm working with the following system call in the Linux kernel that takes a virtual address of a process and outputs the following information:
If the data in this address is in memory or on disk.
If the page which this address belongs to has been referenced or not.
If the page which this address belongs to is dirty or not.
#include<linux/kernel.h>
#include<linux/sched.h>
#include<asm/page.h>
#include<asm/pgtable.h>
#include<linux/mm_types.h>
asmlinkage int sys_vma_props(unsigned long mem,int pid)
{
struct task_struct *task=find_task_by_vpid(pid);
struct mm_struct *memory=task->active_mm;
int data=0;
int ref=0;
int dirty =0;
pgd_t *pgd=pgd_offset(memory,mem);
pud_t *pud=pud_offset(pgd,mem);
pmd_t *pmd=pmd_offset(pud,mem);
ptet_t *ptep=pte_offset_kernel(pmd,mem);
pte_t pte=*ptep;
data=pte_present(pte);
printk("present flag: %i\n",data?1:0);
ref=pte_young(pte);
printk("referenced flag: %i\n",ref?1:0);
dirty=pte_dirty(pte);
printk("dirty flag: %i\n",dirty?1:0);
return 0;
}
However, I'm getting the following error for the ptep_t variable and the ptep variable. I've researched and this makes sense to me so I'm not really sure what the problem is. What's causing the error? Any advice would be much appreciated.
address/sys_vadd.c:19: error: ‘ptep_t’ undeclared (first use in this function)
address/sys_vadd.c:19: error: (Each undeclared identifier is reported only once
address/sys_vadd.c:19: error: for each function it appears in.)
address/sys_vadd.c:19: error: ‘ptep’ undeclared (first use in this function)
address/sys_vadd.c:20: warning: ISO C90 forbids mixed declarations and code

The problem is that you've used the wrong type for the ptep variable. It should be pte_t not ptet_t.

Related

How to access the /proc file system's iiterate function pointer

I am trying to create a simple linux rootkit that can be used to hide processess. The method I have chosen to try is to replace the pointer to "/proc" 's iterate function with a pointer to a custom one that will hide the processess I need. To do this I have to first save a pointer to it's originale iterate function so it can be replaced later. The '/proc' file system's iterate function can be accessed by accessing the 'iterate' function pointer which is a member of it's 'file_operations' structure.
I have tried the following two methods to access it, as can be seen in the code segment as label_1 and label_2, each tested with the other commented out.
static struct file *proc_filp;
static struct proc_dir_entry *test_proc;
static struct proc_dir_entry *proc_root;
static struct file_operations *fs_ops;
int (*proc_iterate) (struct file *, struct dir_context *);
static int __init module_init(void)
{
label_1:
proc_filp = filp_open("/proc", O_RDONLY | O_DIRECTORY, 0);
fs_ops = (struct file_operations *) proc_filp->f_op;
printk(KERN_INFO "file_operations is %p", fs_ops);
proc_iterate = fs_ops->iterate;
printk(KERN_INFO "proc_iterate is %p", proc_iterate);
filp_close(proc_filp, NULL);
label_2:
test_proc = proc_create("test_proc", 0, NULL, &proc_fops);
proc_root = test_proc->parent;
printk(KERN_INFO "proc_root is %p", proc_root);
fs_ops = (struct file_operations *) proc_root->proc_fops;
printk(KERN_INFO "file_operations is %p", fs_ops);
proc_iterate = fs_ops->iterate;
printk(KERN_INFO "proc_iterate is %p", proc_iterate);
remove_proc_entry("test_proc", NULL);
return 0;
}
As per method 1, I open '/proc' as a file, then follow the file pointer to access it's 'struct file_operations' (f_op), and then follow this pointer to try and locate 'iterate'. However, although I am able to successfully access the 'f_op' structure, somehow it's 'iterate' seems to point to NULL. The following dmesg log shows the output of this.
[ 47.707558] file_operations is 00000000b8d10f59
[ 47.707564] proc_iterate is (null)
As per method 2, I create a new proc directory entry, then try to access it's parent directory (which should point to '/proc' itself), and then try to access it's 'struct file_operations' (proc_fops), and then try to follow on to 'iterate'. However, using this method I am not even able to access the '/proc' directory, as 'proc_root = test_proc->parent;' seems to return NULL. This causes a 'kernel NULL pointer dereference' error in the code that follows. The following dmesg log shows the output of this.
[ 212.078552] proc_root is (null)
[ 212.078567] BUG: unable to handle kernel NULL pointer dereference at 000000000000003
Now, I know that things have changed in the linux kernel, and we are not allowed to write at various addresses (like change the iterate pointer to point at a custom function for example) and that this can be overcome by making those pages writable in the kernel, but that will come later in my attempt to create this rootkit. At present I can't even figure out how to even read the original 'iterate' pointer.
So, I have these questions :
[1] Is something wrong in the following code ? How to fix it ?
[2] Is there any other way to access the pointer to the /proc 's iterate function ?
Tested on Arch Linux running linux 4.15.7

How to use proc_pid_cmdline in kernel module

I am writing a kernel module to get the list of pids with their complete process name. The proc_pid_cmdline() gives the complete process name;using same function /proc/*/cmdline gets the complete process name. (struct task_struct) -> comm gives hint of what process it is, but not the complete path.
I have included the function name, but it gives error because it does not know where to find the function.
How to use proc_pid_cmdline() in a module ?
You are not supposed to call proc_pid_cmdline().
It is a non-public function in fs/proc/base.c:
static int proc_pid_cmdline(struct seq_file *m, struct pid_namespace *ns,
struct pid *pid, struct task_struct *task)
However, what it does is simple:
get_cmdline(task, m->buf, PAGE_SIZE);
That is not likely to return the full path though and it will not be possible to determine the full path in every case. The arg[0] value may be overwritten, the file could be deleted or moved, etc. A process may exec() in a way which obscures the original command line, and all kinds of other maladies.
A scan of my Fedora 20 system /proc/*/cmdline turns up all kinds of less-than-useful results:
-F
BUG:
WARNING: at
WARNING: CPU:
INFO: possible recursive locking detecte
ernel BUG at
list_del corruption
list_add corruption
do_IRQ: stack overflow:
ear stack overflow (cur:
eneral protection fault
nable to handle kernel
ouble fault:
RTNL: assertion failed
eek! page_mapcount(page) went negative!
adness at
NETDEV WATCHDOG
ysctl table check failed
: nobody cared
IRQ handler type mismatch
Machine Check Exception:
Machine check events logged
divide error:
bounds:
coprocessor segment overrun:
invalid TSS:
segment not present:
invalid opcode:
alignment check:
stack segment:
fpu exception:
simd exception:
iret exception:
/var/log/messages
--
/usr/bin/abrt-dump-oops
-xtD
I have managed to solve a version of this problem. I wanted to access the cmdline of all PIDs but within the kernel itself (as opposed to a kernel module as the question states), but perhaps these principles can be applied to kernel modules as well?
What I did was, I added the following function to fs/proc/base.c
int proc_get_cmdline(struct task_struct *task, char * buffer) {
int i;
int ret = proc_pid_cmdline(task, buffer);
for(i = 0; i < ret - 1; i++) {
if(buffer[i] == '\0')
buffer[i] = ' ';
}
return 0;
}
I then added the declaration in include/linux/proc_fs.h
int proc_get_cmdline(struct task_struct *, char *);
At this point, I could access the cmdline of all processes within the kernel.
To access the task_struct, perhaps you could refer to kernel: efficient way to find task_struct by pid?.
Once you have the task_struct, you should be able to do something like:
char cmdline[256];
proc_get_cmdline(task, cmdline);
if(strlen(cmdline) > 0)
printk(" cmdline :%s\n", cmdline);
else
printk(" cmdline :%s\n", task->comm);
I was able to obtain the commandline of all processes this way.
To get the full path of the binary behind a process.
char * exepathp;
struct file * exe_file;
struct mm_struct *mm;
char exe_path [1000];
//straight up stolen from get_mm_exe_file
mm = get_task_mm(current);
down_read(&mm->mmap_sem); //lock read
exe_file = mm->exe_file;
if (exe_file) get_file(exe_file);
up_read(&mm->mmap_sem); //unlock read
//reduce exe path to a string
exepathp = d_path( &(exe_file->f_path), exe_path, 1000*sizeof(char) );
Where current is the task struct for the process you are interested in. The variable exepathp gets the string of the full path. This is slightly different than the process cmd, this is the path of binary which was loaded to start the process. Combining this path with the process cmd should give you the full path.

Inline C Varnish (VCL_deliver)

I am using Varnish 4.0.
My backend is adding to some responses an http header "x-count"
I would like to log the value of "x-count" into a file with a line break.
I assumed i should do it in VCL deliver.
Here is what i have so far :
sub vcl_deliver {
if (resp.http.x-count-this:) {
set resp.http.X-infodbg = "xx";
C{
FILE *fp;
fp = fopen("/tmp/test.txt", "w+");
fputs(VRT_GetHdr(sp, HDR_OBJ, "\013x-count-this:"), fp);
fputs("\n", fp);
fclose(fp);
}C
}
}
Of course it doesnt work and there is a couple of errors ..
./vcl.gK2lu7uM.c: In function ‘VGC_function_vcl_deliver’:
./vcl.gK2lu7uM.c:1049:22: error: ‘sp’ undeclared (first use in this
function) ./vcl.gK2lu7uM.c:1049:22: note: each undeclared identifier
is reported only once for each function it appears in
./vcl.gK2lu7uM.c:1049:5: error: passing argument 2 of ‘VRT_GetHdr’
makes pointer from integer without a cast [-Werror]
./vcl.gK2lu7uM.c:330:7: note: expected ‘const struct gethdr_s *’ but
argument is of type ‘int’ ./vcl.gK2lu7uM.c:1049:5: error: too many
arguments to function ‘VRT_GetHdr’ ./vcl.gK2lu7uM.c:330:7: note:
declared here
I have to say that i simply copy/pasted "sp" from some examples, but i have no idea where it comes from (i suppose the inline C was in a different context and therefore it was declared there but not in vcl_deliver)
So the probably undocumented differences between Varnish 4 and 3 in the above examples are :
VRT_GetHdr is now VRT_GetHdr(context, struct gethdr_s)
sp doesn't exist, but there is a "ctx" variable
Found this, there :
http://jan.bogutzki.de/Artikel/395/set-ttl-in-varnish-4.html
char *stuffid;
const struct gethdr_s hdr = { HDR_BERESP, "\015x-count-this:" };
stuffid = VRT_GetHdr(ctx, &hdr);
And now a different story: Varnish is crashing as soon as the backend sends back "count-this", but that is a different problem :p (my crappy C code probably)
I don't have Varnish 4.0 handy to test this out, but I was able to get your example working with Varnish 3.0. When I tried the VCL as is, I wasn't getting the exact error you are though. The first change:
if (resp.http.x-count-this:) {
needs to be:
if (resp.http.x-count-this) {
The colon should be left off of the header name when referred to this way. Next:
fputs(VRT_GetHdr(sp, HDR_OBJ, "\013x-count-this:"), fp);
needs to be:
fputs(VRT_GetHdr(sp, HDR_OBJ, "\015x-count-this:"), fp);
The length value in that string needs to be in octal for some reason, and 13 in octal is 15. Making those changes got this to work for me. That being said, you many want to look into using open and fcntl instead of fopen since without file locking I'm not sure what the effect of multiple requests contending for that file would be.

Haskell FFI stack size with a C++ shared library

I am trying to send a very large amount of data, on the order of several Gigabytes to Haskell via a shared library. Everything seems to work fine up to a point, but I eventually get the error:
Stack space overflow: current size 8388608 bytes.
Use `+RTS -Ksize' to increase it.
So basically, my question is: How do I increase the Haskell stack size?
I have tried:
1) Passing the appropriate -rtsopts flags to the linker when building the shared library -- No luck, but this is expected because I am using the Haskell as a shared library.
2) Calling hs_init with the RTS flags as described in this link:
Haskell User Guide FFI/GHC...which did not work either.
int argc = 2;
char *argv[] = { "+RTS", "-K100M", NULL };
char **pargv = argv;
// Initialize Haskell runtime
hs_init(&argc, &pargv);
Basically I think that these arguments are also ignored because I am not using a Haskell main, which is also described in the user guide link I provided.
NOTE: I have also tried this approach adding a "-RTS" to the list before NULL and increasing argc but it made no difference.
3) I suspect that the true solution to this problem would be by following section 8.2.1.1 in the given link and making the special call to hs_init_ghc as so:
#include "HsFFI.h"
#include "Rts.h"
RtsConfig conf = defaultRtsConfig;
conf.rts_opts_enabled = RtsOptsAll;
hs_init_ghc(&argc, &argv, conf);
However when I try to do this as described in the guide, my C code that calls:
hs_init_ghc
will NOT compile due to a whole bunch of errors which I have pasted into the bottom of this question. It seems that including RTS.h will not compile, but I am following the example exactly, and compiling with:
ghc -c foo.cpp
I am wondering if anyone has any advice on how to get around this compilation error or to set the stack-size to a bigger value when using the Haskell as a shared library from C++?
I have also tried setting the corresponding environment variable, which also did not work. I even got a message saying it will be ignored.
I am using GHC version 7.4.1
Thanks very much for your help.
--JL
Compilation errors are:
>
In file included from /usr/lib/ghc/include/Rts.h:222:0:
0, from foo.cpp:6:
/usr/lib/ghc/include/rts/storage/Block.h:227:26:
error: expected ‘,’ or ‘...’ before ‘new’
dbl_link_replace(bdescr *new, bdescr *old, bdescr **list)
^
/usr/lib/ghc/include/rts/storage/Block.h: In function ‘void dbl_link_replace(bdescr*)’:
/usr/lib/ghc/include/rts/storage/Block.h:229:8:
error: expected type-specifier before ‘->’ token
new->link = old->link;
^
/usr/lib/ghc/include/rts/storage/Block.h:229:8:
error: expected ‘;’ before ‘->’ token
/usr/lib/ghc/include/rts/storage/Block.h:230:8:
error: expected type-specifier before ‘->’ token
new->u.back = old->u.back;
^
/usr/lib/ghc/include/rts/storage/Block.h:230:8:
error: expected ‘;’ before ‘->’ token
/usr/lib/ghc/include/rts/storage/Block.h:231:9:
error: ‘old’ was not declared in this scope
if (old->link) {
^
/usr/lib/ghc/include/rts/storage/Block.h:232:32:
error: expected type-specifier before ‘;’ token
old->link->u.back = new;
^
/usr/lib/ghc/include/rts/storage/Block.h:234:9:
error: ‘old’ was not declared in this scope
if (old->u.back) {
^
/usr/lib/ghc/include/rts/storage/Block.h:235:32:
error: expected type-specifier before ‘;’ token
old->u.back->link = new;
^
/usr/lib/ghc/include/rts/storage/Block.h:237:10:
error: ‘list’ was not declared in this scope
*list = new;
^
/usr/lib/ghc/include/rts/storage/Block.h:237:20:
error: expected type-specifier before ‘;’ token
*list = new;
^
In file included from /usr/lib/ghc/include/Rts.h:218:0:
0,
from foo.cpp:6:
/usr/lib/ghc/include/rts/storage/ClosureMacros.h: In function ‘rtsBool
More compile errors removed...but available upon request.

per-cpu variable definition in Linux kernel 2.6.27

In 2.6.27 there is the macro DEFINE_PER_CPU(type, variable) to define per-cpu variables.
I am able to define a variable in the global scope using this macro. But if its a variable inside a structure I see an error when compiling..
for ex:
struct port_stats {
... ....
DEFINE_PER_CPU(long *, stats);
}
The error I see is..
*error: section attribute not allowed for 'per_cpu__stats'*
The same definition is ok if its outside the structure. Not sure what this error means. Any suggestions ?
If you want to define a per-cpu variable within a struct in the Linux kernel, you need to make it a pointer to the desired type (so, in this case long **) with the __percpu attribute:
struct port_stats {
... ....
long __percpu **stats;
}
(On older kernels that lack the __percpu macro, just declare it as long **stats; with a comment that it is a pointer to an array of per-cpu variables).
Then when you create an instance of the structure, allocate the per-cpu variables with alloc_percpu() (which can fail):
pstats->stats = alloc_percpu(long *);
if (!pstats->stats)
return -ENOMEM;
To then access the percpu instance, you need to use get_cpu() and put_cpu():
long **stats;
stats = per_cpu_ptr(pstats->stats, get_cpu());
/* Read or write *stats, the per-cpu (long *) value for this cpu */
put_cpu();
When you free the structure, you must also execute free_percpu(pstats->stats); as well.

Resources