[Crash-utility] change the content of memory using crash on a live system -- use kprobes!

Dave Anderson anderson at redhat.com
Fri Mar 7 19:44:22 UTC 2008


Dheeraj Sangamkar wrote:
> Thanks a million Dave,
> I will try using the kprobes approach.
> 

One thing I neglected to mention re: the usage of /dev/mem.
Another restriction it has always had (not just in Red Hat
kernels) is this:

static ssize_t read_mem(struct file * file, char __user * buf,
                        size_t count, loff_t *ppos)
{
         unsigned long p = *ppos;
         ssize_t read, sz;
         char *ptr;

         if (!valid_phys_addr_range(p, count))
                 return -EFAULT;

where valid_phys_addr_range() on an x86 restricts access
to lowmem, i.e. the first 896MB of physical memory:

static inline int valid_phys_addr_range(unsigned long addr, size_t count)
{
         if (addr + count > __pa(high_memory))
                 return 0;

         return 1;
}

So if you need to look at a piece of memory above that,
"crash /dev/mem" will fail.  Normally that's not a problem,
if you're trying to access unity-mapped kernel virtual
memory, i.e., where static kernel data, slab data, etc.
exist.  But if it's a user-space address, or a mapped vmalloc()
address, and the PTE's needed to translate that virtual
address exist in highmem, then the physical location
cannot be determined.

That's always been a weakness with the /dev/mem driver,
and again, I don't exactly know why.  The /dev/crash
driver doesn't make the restriction, and AFAICT if the
valid_phys_addr_range() could be also be kprobe'd to return
a 1, then it would mimic /dev/crash.  But it gets inlined
and it's certainly not nearly as simple as the devmem_is_allowed()
probe.  It may be possible, but I don't know how...

Anyway, getting back to your original example:

   crash> struct request_queue 0xf7b933f8
   struct request_queue {
     queue_head = {
   <SNIP>
   ...
   }

It's not clear to me whether 0xf7b933f8 is a vmalloc()
address (like from a module) or right on the edge of
being at the very top of unity-mapped memory.  If it's
a mapped vmalloc() address, then the kprobes hack
won't work "out of the box".  You may have first run
crash with /dev/crash, do a vtop on the vmalloc address
to find its physical address, and then *only* if the
physical address is in lowmem, will you be able to
then subsequently do the kprobes workaround, using
"wr -p" to specify the physical address instead of
the virtual address.

Or reboot your kernel with "mem=896m" to keep all
physical memory below 896MB.

Clear as mud?

Dave




Dave




More information about the Crash-utility mailing list