[Linux-ia64] Re: Fixing /proc/kcore

Mario Smarduch
2002-10-28T16:14:30Z

Tony, Andi thanks!

- mario

Andi Kleen wrote:

> "Luck, Tony" <tony.luck@intel.com> writes:
>
> > This message is in MIME format. Since your mail reader does not understand
> > this format, some or all of this message may not be legible.
> >
> > ------_=_NextPart_000_01C27C4E.CD496DB0
> > Content-Type: text/plain;
> > charset="utf-7"
> >
> > /proc/kcore is what you need, but it is broken on ia64 (and
> > has been since the dawn of time for access to region 5) because
> > it assumes that all kernel virtual addresses are above PAGE_OFFSET.
> > This isn't true on ia64, VMALLOC_START is smaller than PAGE_OFFSET.
>
> I recently fixed a similar problem on x86-64. There the modules are outside
> the vmalloc area, but also not in the direct mapping. I just changed
> the module mapping and the kernel mapping to put themselves into the vmlist.
> kcore checks vmlist first and then afterwards tries direct addresses.
>
> Also the kernel addresses are negative, which needed some more changes
> in seek.
>
> Here is the 2.4.19 patch which should to 2.5 too.
>
> I think it's a bit cleaner than yours and will probably help you too.
> Just put everything special into vmlist too.
>
> -Andi
>
> Index: linux/fs/proc/inode.c
> =================================> RCS file: /home/cvs/Repository/linux/fs/proc/inode.c,v
> retrieving revision 1.4
> retrieving revision 1.5
> diff -u -u -r1.4 -r1.5
> --- linux/fs/proc/inode.c 2002/01/15 10:09:21 1.4
> --- linux/fs/proc/inode.c 2002/10/17 13:02:13 1.5
> @@ -186,6 +184-,7 @@
> s->s_blocksize_bits = 10;
> s->s_magic = PROC_SUPER_MAGIC;
> s->s_op = &proc_sops;
> s->s_maxbytes = +AH4-0ULL;
>
> root_inode = proc_get_inode(s, PROC_ROOT_INO, &proc_root);
> if (!root_inode)
> Index: linux/fs/proc/kcore.c
> =================================> RCS file: /home/cvs/Repository/linux/fs/proc/kcore.c,v
> retrieving revision 1.3
> retrieving revision 1.4
> diff -u -u -r1.3 -r1.4
> --- linux/fs/proc/kcore.c 2002/03/21 11:54:59 1.3
> --- linux/fs/proc/kcore.c 2002/10/17 13:02:13 1.4
> @@ -27,11 ,14 @@
> return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
> }
>
> +statiQ- loff_t lseek_kcore(struct file * file, loff_t offset, int origin);
>
> static ssize_t read_kcore(struct file *, char *, size_t, loff_t *);
>
> struct file_operations proc_kcore_operations = {
> read: read_kcore,
> open: open_kcore,
> lseek: lseek_kcore,
> };
>
> #ifdef CONFIG_KCORE_AOUT
> @@ -112,9 +114-,9 @@
>
> extern char saved_command_line[];
>
> -static size_t get_kcore_size(int *num_vma, size_t *elf_buflen)
> +statiQ- unsigned long get_kcore_size(int *num_vma, size_t *elf_buflen)
> {
> - size_t try, size;
> unsigned long try, size;
> struct vm_struct *m;
>
> *num_vma = 0;
> @@ -125,7 +128-,7 @@
> }
>
> for (m=vmlist; m; m=m->next) {
> - try = (size_t)m->addr m->size;
> try = (unsigned long)m->addr m->size;
> if (try > size)
> size = try;
> *num_vma = *num_vma 1;
> @@ -313,14 +314-,14 @@
> static ssize_t read_kcore(struct file *file, char *buffer, size_t buflen, loff_t *fpos)
> {
> ssize_t acc = 0;
> - size_t size, tsz;
> unsigned long size, tsz;
> size_t elf_buflen;
> int num_vma;
> unsigned long start;
>
> read_lock(&vmlist_lock);
> proc_root_kcore->size = size = get_kcore_size(&num_vma, &elf_buflen);
> - if (buflen = 0 || *fpos >= size) {
> if (buflen = 0 || (unsigned long long)*fpos >= size) {
> read_unlock(&vmlist_lock);
> return 0;
> }
> @@ -390,9 +390-,16 @@
> start = PAGE_OFFSET (*fpos - elf_buflen);
> if ((tsz = (PAGE_SIZE - (start & +AH4-PAGE_MASK))) > buflen)
> tsz = buflen;
> -
> while (buflen) {
> - if ((start >= VMALLOC_START) && (start < VMALLOC_END)) {
> int err;
>
> if ((start > PAGE_OFFSET) && (start < (unsigned long)high_memory)) {
> if (kern_addr_valid(start)) {
> err = copy_to_user(buffer, (char *)start, tsz);
> } else {
> err = clear_user(buffer, tsz);
> }
> } else {
> char * elf_buf;
> struct vm_struct *m;
> unsigned long curstart = start;
> @@ -432,24 +440-,11 @@
> (char *)vmstart, vmsize);
> }
> read_unlock(&vmlist_lock);
> - if (copy_to_user(buffer, elf_buf, tsz)) {
> - kfree(elf_buf);
> - return -EFAULT;
> - }
> err = copy_to_user(buffer, elf_buf, tsz);
> kfree(elf_buf);
> - } else if ((start > PAGE_OFFSET) && (start <
> - (unsigned long)high_memory)) {
> - if (kern_addr_valid(start)) {
> - if (copy_to_user(buffer, (char *)start, tsz))
> - return -EFAULT;
> - } else {
> - if (clear_user(buffer, tsz))
> - return -EFAULT;
> - }
> - } else {
> - if (clear_user(buffer, tsz))
> - return -EFAULT;
> - }
> }
> if (err)
> return -EFAULT;
> buflen -= tsz;
> *fpos = tsz;
> buffer = tsz;
> @@ -461,3 +458-,19 @@
> return acc;
> }
> #endif /* CONFIG_KCORE_AOUT */
>
> +statiQ- loff_t lseek_kcore(struct file * file, loff_t offset, int origin)
> {
> long long retval;
>
> switch (origin) {
> case 2:
> offset = file->f_dentry->d_inode->i_size;
> break;
> case 1:
> offset = file->f_pos;
> }
> /* RED-PEN user can fake an error here by setting offset to >=-4095 && <0 */
> file->f_pos = offset;
> return offset;
> }