root cannot write to Linux RAM


void main() {

long ((long)(&array));
int x;
for (;;)
{
(array) =+ 1023;
printf("%c", array[0]);

}


}


What is wrong with this code to print Linux RAM?

That looks like some weird sort of function pointer, not an array. I'm not sure what you're even trying to do.

Even when running as root, your program gets run in user space, with its own private, virtual memory layout. You literally don't have any memory except pages the kernel has given you, every memory access is checked in hardware. Stray outside that range and your process dies with SEGV like any other.

My errors;

Okay. Nothing to do with root then, since your program didn't even compile.

What are you trying to do? I can't show you how to do that until you explain what you actually want.

The Linux kernel is in RAM. I want write access to that location.

---------- Post updated at 06:24 PM ---------- Previous update was at 06:21 PM ----------

I'm using a Samsung with VIA processor. 64x. Fedora x64 14.00

Any ideas?

You agreed not to bump posts when you registered. If we don't answer instantly, wait!

Your program isn't running in real mode. You can't access physical addresses just by plugging in the right pointer.

The kernel keeps a list of what memory belongs to your process, and what address your process uses them at. It could give you physical memory address 0x0000000 but make it appear in your process at 0x80000000. And using any virtual addresses that haven't been assigned just causes SEGV. This is all handled in hardware by your processor.

If you want to access physical addresses in Linux, you have to actually ask for them. There's special device files you can read from to get it. /dev/kmem will be the kernel memory area and nothing but the kernel memory area. /dev/mem, I think, is raw RAM contents -- not that useful since the real pages could be scrambled in any virtual order inside the processes themselves. There's also things like memory holes for I/O to consider.

char buf[16384];
int fd=open("/dev/kmem", O_RDONLY);
read(fd, buf, 16384); // first 16KB of kernel mem

Update: The above code produced this output. With a lil few changes.

This is really strange. Where is the kernel?

My code doesn't print anything at all, actually. What did you actually do? It looks like you're printing your own stack and environment space.

Stuff read raw out of arbitrary memory is very unlikely to be sensibly printable.

void main() {

char buf[16384];
int fd=open("/dev/kmem", 'r');
read(fd, buf, 16384); // first 16KB of kernel mem
int x;
for(x =0;;x++) {

printf("%c", buf[x]);

}


}


This is the modified code.

Apologies for writing to you again. But, my purpose of this code is to write 'Alux' to RAM, then read it back again. In the kernel. I used to do similar things on the Commodore 64. There was a 'poke' command.

void main() {

char buf[16384];
int fd=open("/dev/kmem", 'r');
int x, y;
int *test;
for (y = 0; y < 18446744073709551615; y++) {
read(fd, buf, 16384); // first 16KB of kernel mem
test = fd;
for(x =0;x < 16384;x++) {

printf("%c", test[x]);

}

}
close(fd);
}

Done.

int main(void)
{
        char buf[16];
        strcpy(buf, "Alux");
        printf("%s\n", buf);
}

What for? Putting 'Alux' in some random spot of kernel memory would crash the machine.

The commodore 64 had no memory management, few to no sensible programming languages, and no kernel, just a BIOS. You could get away with poke-ing random things, and frequently had to to get around language and BIOS limitations.

Linux has proper memory management, which makes poke kind of pointless. It also has a kernel, which gives you much, much better ways to do what you want than poke. Nobody has to poke anymore, there's no point.

Modern I/O is a lot more complicated than that, anyway. There's not a lot to be accomplished by poking random addresses.

Dear Corona,

The Poke command is very useful in testing ASM scripts. Also, there should be an ability to access RAM. Especially Kernel RAM. That'd be cool! Imagine!

Where is the FSF?

Oh, and what about the ability to write a program to floppy, and let Linux boot the raw binary.

I should clear something up, here. This program, written in C:

int main(void)
{
        char buf[16];
        strcpy(buf, "Alux");
        printf("%s\n", buf);
}

...is translated directly into assembly language, to wit:

        .file   "alux.c"
        .section        .rodata
.LC0:
        .string "Alux"
        .text
.globl main
        .type   main, @function
main:
        pushl   %ebp
        movl    %esp, %ebp
        andl    $-16, %esp
        subl    $32, %esp
        movl    $5, 8(%esp)
        movl    $.LC0, 4(%esp)
        leal    16(%esp), %eax
        movl    %eax, (%esp)
        call    memcpy
        leal    16(%esp), %eax
        movl    %eax, (%esp)
        call    puts
        leave
        ret
        .size   main, .-main
        .ident  "GCC: (Gentoo 4.4.4-r2 p1.2, pie-0.4.5) 4.4.4"
        .section        .note.GNU-stack,"",@progbits

Variables in C already are real, physical memory used as directly as it gets. Declaring a variable in C just instructs the compiler how you want the memory arranged, and follows your instructions when it creates the program in assembly. So this program does in fact write "Alux" into a given spot of memory, directly.

When programming in C you're programming far more directly than you ever did in Commodore BASIC, poke or no.

---------- Post updated at 02:13 PM ---------- Previous update was at 02:02 PM ----------

Not really. In a machine with virtual memory, you don't know where anything is anymore, and devices are probably already in use. It's like keeping a great big TSR around that keeps stomping on everything.

If you wanted to play with registers, ram, and I/O in that manner, try freedos.

---------- Post updated at 03:08 PM ---------- Previous update was at 02:13 PM ----------

You can still read kernel memory though.

#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>

int main(void)
{
        char buf[16384];
        memset(buf, 0, sizeof(buf));
        int fd=open("/dev/kmem", O_RDONLY); // Must be O_RDONLY
        read(fd, buf, 16384);
        write(1, buf, 16384);
}

---------- Post updated at 03:16 PM ---------- Previous update was at 03:08 PM ----------

You also sound like the sort of programmer who might appreciate A Whirlwind Tutorial on Creating Really Teensy ELF Executables for Linux. Quite a lot has changed since the Commodore 64 days, and a good demonstration of what's happening at the assembly level might help complete your picture.

OK, I want my code above to work with Linux. I'm an out of work systems hacker and this seems like a fun way of passing the time.

Some questions;

1.Do Linux Device Drivers operate at Ring 0?

  1. Would the ability to read and update Kernel memory require writing a device driver or changing the Memory Management of Linux?

My main concern is the 'freeing' of the Linux kernel. So that the safety comes off, and the ability to make live updates without server downtime are possible.

Plus, such a feature would be fun! *smiles*

Corona, you hinted at a /dev/kmem file. I'm new to Linux systems programming, but have a couple of books on writing device drivers for Linux.

My ideas at this point are double;

  1. /dev/kmem returns a raw dump of memory without formatting

  2. /dev/kmem returns a formatted hexidecimal / Intel ASM output of the RAM in columns sided with RAM Addresses

My paths are thus;

  1. Access the Global descriptor table task state segment of the kernel to obtain RAM values for access at a later point in the device driver. (Is that possible?)

  2. Access the Process Table in Linux for a list of processes and start/stop address blocks. (Unsafe?)

So many questions at this point in time, not sure where to go for guidance on Linux systems programming.

Oh, if anyone when reading this post suddenly has a website link they think would be useful, or a book to purchase to help, any resources actually, I'd be happy to read up on the subject to make this idea possible.

Basically, what I want is to do the following in C;

void main() {

fd = open("/dev/kmem", 'rw');

// fd opens to beginning of kernel space in RAM

poke_ram(fd, $var);

seek(fd);

read(fd, buf...);

process(fd);

close(fd);

}
}


Rather simple idea? But how to make this code work with Linux?

Thank you for taking the time to read about my new idea.

I'm currently working on my own OS. It runs only in ring 0, and has full access to the RAM and kernel code. Never enters ring 4. Have you heard about self-modifying code? That is a passion of mine. The OS currently only is in text mode, protected mode with segmentation, and has a blue sky with white stars signifying the beginning of the end.

Remember that this is an open-source operating system. There's bound to have been people who've wanted to do the same things you have, and they've been building these features right into the kernel for going on 19 years.

Process tables are directly available including their memory layout, statistics, environment, file and stack and anonymous mappings, open files and sockets, process limits and priority, page maps, user id's, and raw memory contents, via the special /proc/ folder, for each and every process in the system.

Global information is also available under /proc/ on interrupts, DMA, CPU or CPUs, system memory I/O maps, I/O ports, and loaded device drivers.

Low and high-level access to disk, optical, terminal, keyboard, mouse, serial, video input, video output, audio I/O and audio mixing, some CPU features like high-precision timers, and more are available in /dev/.

Comprehensive, detailed, live, and sometimes even writable information on devices, buses, CPUs and CPU features, power saving features, sleep states, power saving states, device drivers, individual options for device drivers, hardware monitoring devices, information on board and CPU firmware, and many more things I don't have any idea what they do yet are are available under /sys/.

They've done things I didn't even think were possible, like kernel debuggers.

Documentation on these things is available in the Documentation folder of the linux kernel source code.

Whatever you want to do, there's almost certainly better ways to do it than poke-ing RAM. And if there isn't, someone would probably thank you for making a device driver for it so they don't have to poke RAM anymore.

I've already given you an outline which isn't pseudocode, but if you're wanting me to explain the entire C language to you that's going to take a long time. Start reading the manual pages for these commands to understand how to use them in other ways. 'man 2 open' for instance shows you what headers to include, what flags work with it(O_RDONLY, O_RDWR, and so forth), how it responds to errors, what errors might occur, and a syllabus of related system calls like the 'lseek' you were looking for. If you don't have manual pages available on your system, you can use the 'man pages' link above to find manuals for linux and a variety of other systems right on unix.com.

There's more fundamental problems. How do you know poking is going to do anything? This isn't a Commodore. Memory context isn't always the same even inside the kernel, writing to the correct address often isn't enough. The right context to do so may only be available inside the kernel, and even then, only when you ask for it first.

Why bother running an operating system when you won't let it do its job?

I believe so.

It'd be done more sensibly inside a kernel driver than poking from the outside. You wouldn't have to chart out memory and pick addresses and hope they never change behind your back, just use variables and get what you asked for.

Linux already does this with modules. Device drivers can be loaded, unloaded, replaced, and reloaded at runtime. Really quite a lot of the kernel can be made as modules now, not just device drivers but entire feature sets. Even your disk drivers -- you can get around the catch-22 of loading disk drivers from disk by using an initramfs system, a tiny preloaded ramdrive that the bootloader sets up for you.

When modules won't do, linux already has the new kexec feature to load a new kernel without rebooting. kexec is also handy to load completely different OSes without the hassle of going through POST again.

Your first guess is the more correct one, I think.

This isn't your commodore, memory can move. How do you know values you grab now are going to make any sense later? How do you know what you ask for is even going to be in memory and not in swap?

This is what I've been telling you. You don't need poke. The process table and comprehensive information on processes is already available via the special /proc/ folder.

How about self-modifying code which saves itself to file, so next time you run it, the changes are still there? Possible in UNIX with mmap() and mprotect() -- map a memory area in from a file, set it readable, writable, and executable, then go to town. Any changes you make to it will be saved to file without any more intervention on your part.

Much easier when you use an operating system instead of fighting it.