Re: Printing environment variables for a process

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Yes, it is possible.
The mm_struct structure has two members called env_start and env_end, both of them are user space linear addresses, so you can easily get the starting address of the environment ( env_start ) and the length (env_end - env_start).

The problem is how do you access to this env. buffer while you are in kernel mode. You cannot simply use copy_from_user, because the current pgd (current->pgd) is not the same as the task pgd you want to get the environment.

Does the kernel provide any method to copy data from user space using a different pgd ? If it does, I could not find it yet.

I wrote a function that do this (copy_from_user_space() ) and another one to dump the environment of a task (using its pid) to the kernel ring buffer. (I have just tested over i386).

If someone knows a more efficient (or elegant) way of do this, please let me know.

Best Regards.

int copy_from_user_space(void *to, void *from, struct mm_struct *mm, unsigned long n)
{
    unsigned long copied = 0;
    pgd_t *pgd = pgd_offset(mm, (unsigned long) from);
    pud_t *pud;
    pmd_t *pmd;
    pte_t *ptep, pte;
    struct page *page;
    unsigned long src_offset = (unsigned long)from & (PAGE_SIZE - 1);

    while (copied < n)
    {
        unsigned long bytes_to_end = PAGE_SIZE - src_offset;
        page = NULL;
        bytes_to_end = ( bytes_to_end < (n-copied) ) ? bytes_to_end : (n-copied);
 
        if (!pgd_none(*pgd)) {
            pud = pud_offset(pgd, (unsigned long) from);
            if (!pud_none(*pud)) {
                pmd = pmd_offset(pud, (unsigned long) from);
                if (!pmd_none(*pmd)) {
                    ptep = pte_offset_map(pmd, (unsigned long) from);
                    pte = *ptep;
                    if (pte_present(pte)) {
                        page = pte_page(pte);
                    }
                    pte_unmap(ptep);
                }
            }
        }

        if (page)
        {
            void *addr = kmap(page);
            memcpy(to + copied, addr + src_offset, bytes_to_end);
            kunmap(page);
            copied += bytes_to_end;
        }
        else {
            return -1;
        }
        src_offset = 0;

    }

    return 0;
}

int dump_env(int pid)
{
    struct task_struct *task;
    struct mm_struct *mm;
    int i;
    char *buff;
    int buff_len;
    unsigned long ret;
   

    printk("pid %d\n", pid);
    if (pid==-1)
        return -1;

    task = find_task_by_pid(pid);
    if (!task)
    {
        printk("could not find task\n");
        return -1;
    }
    if (task->comm)
        printk("Task: %s\n", task->comm);

    mm = task->mm;

    buff_len = mm->env_end - mm->env_start;

    buff = kmalloc( buff_len, GFP_KERNEL);

    if (!buff)
        return -1;

    ret = copy_from_user_space( buff, (void *) mm->env_start, mm, buff_len);

    printk("**************** Environment *****************\n");
    for(i=0 ; i<buff_len ; i++)
    {
        printk("%c", buff[i] ? buff[i] : '\n');   
    }
       
    printk("\n********************************************\n");
    kfree(buff);

    return 0;
}



On Jan 29, 2008 11:17 AM, Manish Katiyar <mkatiyar@xxxxxxxxx> wrote:
Hi,

Is it possible to print or access the environment variables of a
process from kernel module. I know it can be done from userspace, but
if there is a running process I don't know if there is any way to
access/print the environment of a process from userspace. So I thought
if it is possible to write a module which accepts a pid during load
and then prints its environment variables.

I tried looking at task_struct to see which member holds the
environment, but cudnt get much. Any help appreciated.

--
Thanks & Regards,
********************************************
Manish Katiyar  ( http://mkatiyar.googlepages.com )
3rd Floor, Fair Winds Block
EGL Software Park
Off Intermediate Ring Road
Bangalore 560071, India
***********************************************

--
To unsubscribe from this list: send an email with
"unsubscribe kernelnewbies" to ecartis@xxxxxxxxxxxx
Please read the FAQ at http://kernelnewbies.org/FAQ



[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux