How to change page table entry to induce page fault in linux? - linux

I am trying to estimate WSS (Working set size) of a process using a custom kernel and kernel module.
I first locate the task_struct of the process and iterate through all the vm areas from mm_struct. I was able to access all PTE's by walking the page table and check if page is present and estimate the RSS (Resident set size).
What I want to do now is change the PTE of VM areas such that it will cause page fault and my custom kernel will log the pagefaults in my required address range. From the page faults, I can estimate WSS. But when I try to change the _PAGE_PRESENT or _PAGE_PROTNONE, I get swap_dup: Bad swap file entry error and process crashes. Why isn't the actual page fault mechanism working when the flag is changed? What am I doing wrong?
This is my code snippet
for (addr = vmstart->vm_start; addr < vmstart->vm_end; addr += PAGE_SIZE) {
//Get PTE by walking page table
pte_t *pte = walk_page_table(task->mm,addr),tmp_pte;
//Only count present addresses:
if(pte && (pte_val(*pte) & _PAGE_PRESENT)) {
tmp_pte = *pte;
set_pte(pte , pte_clear_flags(tmp_pte, _PAGE_PRESENT) );
printk(KERN_INFO "Flag changed at %lx , Name %s\n", addr,name);
}
}
//unmap accessed page
if(pte) pte_unmap(pte);
}
walk_page_table returns pte of given virtual address. Please give suggessions.
The errors I get are
swap_dup: Bad swap file entry
BUG: Bad page map in process

Swap page PTEs and in memory pages PTEs have completely different structure. Swap entries shows where pages are placed in the second storage, while normal PTEs describes physical page address + flags.
So, actually, the page fault mechanism is working, but where your page fault handler should search for swapped (no page present flag) page?

Related

PerformanceResourceTiming.transferSize returns 0 in some webpages

I'm trying to get the total transfer size of some web pages. I don't know why but some web pages are returning 0 octets. I'm trying this snippet to get total transfer size;
var fetchedResourcesArray = performance.getEntriesByType("resource");
var totalTransferSize = 0;
for (var resourceIndex = 0; resourceIndex < fetchedResourcesArray.length; resourceIndex++) {
totalTransferSize += parseInt(fetchedResourcesArray[resourceIndex].transferSize);
}
which is very similar to an example of MDN: https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/transferSize
When I test this snippet for example on youtube, I don't have any problem getting transfer size in this way but when I try this snippet on twitter, it always returns 0 even it downloads and fetches many resources. How can I track total download size of web apps like twitter?
I believe the reason for this is to do with CORS. See the note at https://developer.mozilla.org/en-US/docs/Web/API/Resource_Timing_API#Resource_loading_timestamps.
When CORS is in effect, many of these values are returned as zero unless the server's access policy permits these values to be shared. This requires the server providing the resource to send the Timing-Allow-Origin HTTP response header with a value specifying the origin or origins which are allowed to get the restricted timestamp values.
The properties which are returned as 0 by default when loading a resource from a domain other than the one of the web page itself: redirectStart, redirectEnd, domainLookupStart, domainLookupEnd, connectStart, connectEnd, secureConnectionStart, requestStart, and responseStart.
I suspect that some of the elements on those pages come from a different origin (CORS) and the Timing-Allow-Origin header is missing.

Retrieving session Id in linux kernel (Kernel Space)

I want to retrieve the sessionid of the current process in linux kernel (Kernel Space). I saw task_struct has a field sessionid but it is defined only when the macro CONFIG_AUDITSYSCALL is ON. So i tried to build the kernel with this macro ON but still i was not getting the result. Also I tried getting its value from function with CONFIG_AUDITSYSCALL on audit_get_sessionid(current) but was getting either -1 or junk value ( different from getsid(0) method in user space).
I am struck at this point. Any suggestion would be of great help.
You can take a look at the getsid syscall at here: http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=kernel/sys.c#l1106
SYSCALL_DEFINE1(getsid, pid_t, pid)
{
struct task_struct *p;
struct pid *sid;
int retval;
rcu_read_lock();
if (!pid)
sid = task_session(current);
else {
...
Which suggest you can use the kernel function task_session() to get the session id.
pid_vnr(task_session(current)); would do what u want!!

Get starting address of a memory page in Linux

In my code, I need to keep track of some pages which are being modified. Initially I give only read access to them, but on the signal handler I give them both read and write access (I am not going to explain what is the purpose for all that and there is actually more code in the signal handler, which I've not shown).
Now my question is how to get the starting address of a page from a memory address which resides in that page. So basically I need to implement the get_page_start_addr shown here in the code. Up till now, I was only doing it for a single page, whose starting address my program knew. But now, since I need to do it for multiple pages, I need to get the starting address of the page from any arbitrary memory address, because mprotect only accepts starting page address as valid argument.
static void memory_change_handler(int sig, siginfo_t *si, void *unused)
{
long addr = (long)si->si_addr;
long page_start_addr = get_page_start_addr( addr );
if (mprotect((void*)page_start_addr, pagesize, PROT_READ | PROT_WRITE) == -1)
{
print_error();
handle_error("mprotect");
}
}
In Linux (in other OSes too, I guess), pages are aligned at page boundaries. Thus, if you know your PAGE_SIZE, then you can simply get the start of the page by masking the lower address bits.
page_start = addr & ~(PAGE_SIZE-1);
To portably know your pagesize, use sysconf(_SC_PAGESIZE).
You can take that address (unsigned long) /pagesize and *pagesize.
This gives you the first page address of your logical address.

How does NSURLCache work in iOS 4?

When I learn NSURLCache documentation I can't find many important notes.
I found that many topics in web complain that NSURLConnection that use NSURLCache had memory leaks. When I tried to write some application for iOS 4.3 I found that MSURLCache have some strange behavior.
In application:didFinishLaunchingWithOptions: I set instance of NSURLCache with memory capacity 10MB, init NSURLRequest with NSURLRequestUseProtocolCachePolicy but I can't recieve connection:willCacheResponse: message in my NSURLConnection delegate. When I checked memory capacity in different points of my application, it was 0MB. Why? May be Apple fix some memory leaks by setting NSURLCache memory capacity to 0? I created custom NSURLCache and overrided setMemoryCapacity: method by this:
-(void)setMemoryCapacity:(NSUInteger)memoryCapacity {
if (memoryCapacity > 0) {
[super setMemoryCapacity:memoryCapacity];
}
else {
NSLog(#"zero here");
}
}
Then I started to debug. There is some input text in my app, where user put some url. New setMemoryCapacity: method has been called twice: in my app delegate, when I set capacity to 10MB and (it is very interesting) when user set focus to text input (parameter of memoryCapacity was 0 and I recieve "zero here" string in log). After that I recieved connection:willCacheResponse: messages to NSURLConnection delegate.
It was very strange. I can't understand why. I can't find things in manual about this. Do you have some thoughts?

Linux/X11 input library without creating a window

Is there a good library to use for gathering user input in Linux from the mouse/keyboard/joystick that doesn't force you to create a visible window to do so? SDL lets you get user input in a reasonable way, but seems to force you to create a window, which is troublesome if you have abstracted control so the control machine doesn't have to be the same as the render machine. However, if the control and render machines are the same, this results in an ugly little SDL window on top of your display.
Edit To Clarify:
The renderer has an output window, in its normal use case, that window is full screen, except when they are both running on the same computer, just so it is possible to give the controller focus. There can actually be multiple renderers displaying a different view of the same data on different computers all controlled by the same controller, hence the total decoupling of the input from the output (Making taking advantage of the built in X11 client/server stuff for display less useable) Also, multiple controller applications for one renderer is also possible. Communication between the controllers and renderers is via sockets.
OK, if you're under X11 and you want to get the kbd, you need to do a grab.
If you're not, my only good answer is ncurses from a terminal.
Here's how you grab everything from the keyboard and release again:
/* Demo code, needs more error checking, compile
* with "gcc nameofthisfile.c -lX11".
/* weird formatting for markdown follows. argh! */
#include <X11/Xlib.h>
int main(int argc, char **argv)
{
Display *dpy;
XEvent ev;
char *s;
unsigned int kc;
int quit = 0;
if (NULL==(dpy=XOpenDisplay(NULL))) {
perror(argv[0]);
exit(1);
}
/*
* You might want to warp the pointer to somewhere that you know
* is not associated with anything that will drain events.
* (void)XWarpPointer(dpy, None, DefaultRootWindow(dpy), 0, 0, 0, 0, x, y);
*/
XGrabKeyboard(dpy, DefaultRootWindow(dpy),
True, GrabModeAsync, GrabModeAsync, CurrentTime);
printf("KEYBOARD GRABBED! Hit 'q' to quit!\n"
"If this job is killed or you get stuck, use Ctrl-Alt-F1\n"
"to switch to a console (if possible) and run something that\n"
"ungrabs the keyboard.\n");
/* A very simple event loop: start at "man XEvent" for more info. */
/* Also see "apropos XGrab" for various ways to lock down access to
* certain types of info. coming out of or going into the server */
for (;!quit;) {
XNextEvent(dpy, &ev);
switch (ev.type) {
case KeyPress:
kc = ((XKeyPressedEvent*)&ev)->keycode;
s = XKeysymToString(XKeycodeToKeysym(dpy, kc, 0));
/* s is NULL or a static no-touchy return string. */
if (s) printf("KEY:%s\n", s);
if (!strcmp(s, "q")) quit=~0;
break;
case Expose:
/* Often, it's a good idea to drain residual exposes to
* avoid visiting Blinky's Fun Club. */
while (XCheckTypedEvent(dpy, Expose, &ev)) /* empty body */ ;
break;
case ButtonPress:
case ButtonRelease:
case KeyRelease:
case MotionNotify:
case ConfigureNotify:
default:
break;
}
}
XUngrabKeyboard(dpy, CurrentTime);
if (XCloseDisplay(dpy)) {
perror(argv[0]);
exit(1);
}
return 0;
}
Run this from a terminal and all kbd events should hit it. I'm testing it under Xorg
but it uses venerable, stable Xlib mechanisms.
Hope this helps.
BE CAREFUL with grabs under X. When you're new to them, sometimes it's a good
idea to start a time delay process that will ungrab the server when you're
testing code and let it sit and run and ungrab every couple of minutes.
It saves having to kill or switch away from the server to externally reset state.
From here, I'll leave it to you to decide how to multiplex renderes. Read
the XGrabKeyboard docs and XEvent docs to get started.
If you have small windows exposed at the screen corners, you could jam
the pointer into one corner to select a controller. XWarpPointer can
shove the pointer to one of them as well from code.
One more point: you can grab the pointer as well, and other resources. If you had one controller running on the box in front of which you sit, you could use keyboard and mouse input to switch it between open sockets with different renderers. You shouldn't need to resize the output window to less than full screen anymore with this approach, ever. With more work, you could actually drop alpha-blended overlays on top using the SHAPE and COMPOSITE extensions to get a nice overlay feature in response to user input (which might count as gilding the lily).
For the mouse you can use GPM.
I'm not sure off the top of my head for keyboard or joystick.
It probably wouldn't be too bad to read directly off there /dev files if need be.
Hope it helps

Resources