lkml.org 
[lkml]   [1998]   [May]   [29]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    SubjectRe: 2.1.103: Still "Ugh at c0111691"
    From
    Date
    deas@uni-hamburg.de (Andreas Steffan) writes:

    > Ok, here it is - all in one:
    >
    > Using `/System.map' to map addresses to symbols.
    >
    > May 28 19:02:12 mortimer kernel: Ugh at c0111b34
    > May 28 19:02:12 mortimer kernel: Ugh: process mgetty touched user space while interrupts disabled
    > >>EIP: c0111b48 <do_page_fault+80/3cc>
    > Trace: c0111b48 <do_page_fault+80/3cc>
    > Trace: c01a8c7d <bad_pmd_string+1a1/320>
    > Trace: c0111b34 <do_page_fault+6c/3cc>
    > Trace: c014154b <inode_getblk+47/1b8>
    > Trace: c010a060 <error_code+30/40>
    > Trace: c01a3a6d <__get_user_1+d/14>
    > Trace: c48222c2
    > Trace: c481ea11
    > Trace: c0177562 <write_chan+17e/224>
    > Trace: c01732f9 <tty_write+115/164>
    > Trace: c0177562 <write_chan+17e/224>
    > Trace: c01298ad <sys_write+131/1b0>
    > Trace: c01732f9 <tty_write+115/164>
    > Trace: c0109ee8 <system_call+38/40>
    >
    > Hope this helps. Please let me know, if you need more.
    >
    > -- Andreas

    If I understand the output right, the sequence is:
    system_call -> sys_write -> write_chan -> tty_write ->
    write_chan -> ?? -> ?? -> __get_user (page fault) ->
    do_pagefault.

    The last two seems to be bogus output generated by generate_ugh_trace.
    I'm not sure about inode_get_block and the first tty_write, but the
    interesting points seem to be the two module addresses between
    write_chan and __get_user. Can you load your modules with the '-m'
    option to generate a load map that allows to map addresses to symbols
    (or compile your kernel without using modules)?

    Or is there an easier way to do that (especially after the trace is
    generated)?

    ...

    My guess is that the responsible module is the isdn module (Maybe you
    can verify this using the maps generated by insmod -m or by compiling
    the isdn stuff into the kernel). If you look at
    /drivers/char/isdn/isdn_tty.c you can read:

    cli();
    while (1) {
    ...
    if (from_user)
    copy_from_user(&(info->xmit_buf[info->xmit_count
    ...
    restore_flags(flags);

    Somehow I thought this was fixed in a current version of the ISDN
    subsystem, but either it wasn't or the fixes are not in the current
    kernel.

    Another place where such bug still exists is drivers/char/esp.c. All
    character drivers seem to use the same scheme to implement its
    .*_write functions. They usually disable interrupts, copy data from or
    to user space and enable interrupts again. There is a great chance
    that all drivers are raising pagefaults(Ugh).
    I haven't looked at all drivers but here are some examples:

    ***********
    esp.c:

    static int rs_write(struct tty_struct * tty, int from_user,
    const unsigned char *buf, int count)
    {
    save_flags(flags);
    while (1) {
    cli();
    if (from_user) {
    c -= copy_from_user(tmp_buf, buf, c);
    restore_flags(flags);
    }

    }
    ***********
    istallion.c

    static int stli_write(struct tty_struct *tty, int from_user, const unsigned char
    *buf, int count)
    {
    if (from_user) {
    save_flags(flags);
    cli();
    copy_from_user(stli_tmpwritebuf, chbuf, count);
    restore_flags(flags);
    }
    }
    static ssize_t stli_memwrite(struct file *fp, const char *buf, size_t count, lof
    f_t *offp)
    {
    cli();
    EBRDENABLE(brdp);
    while (size > 0) {
    copy_from_user(memptr, chbuf, n);
    }
    EBRDDISABLE(brdp);
    restore_flags(flags);
    }
    ***********
    cyclade.c

    static int
    cy_write(struct tty_struct * tty, int from_user,
    const unsigned char *buf, int count)
    {
    save_flags(flags);
    while (1) {
    cli();
    if (from_user) {
    copy_from_user(tmp_buf, buf, c);
    restore_flags(flags);
    } /* cy_write */
    ***********
    epca.c

    static int pc_write(struct tty_struct * tty, int from_user,
    const unsigned char *buf, int bytesAvailable)
    { /* Begin pc_write */
    if (from_user)
    { /* Begin from_user */

    save_flags(flags);
    cli();
    copy_from_user(ch->tmp_buf, buf, bytesAvailable)
    restore_flags(flags);

    } /* End from_user */
    }
    ***********
    pcxx.c

    static int pcxe_write(struct tty_struct * tty, int from_user, const unsigned cha
    r *buf, int count)
    {
    if (from_user) {

    save_flags(flags);
    cli();
    if (count) {
    if (verify_area(VERIFY_READ, (char*)buf, count))
    count=0;
    else copy_from_user(ch->tmp_buf, buf, count);
    }
    restore_flags(flags);
    }
    }

    Other files (riscom8.c, rocket.c, specialix.c, stallion.c) are
    following the same scheme. Maybe all drivers should be fixed using the
    model of serial.c. It had the same bug in some previous version and
    seems to be correct now.

    Some of the isdn files have the same problem:

    **************
    isdn_common.c

    static int
    isdn_set_allcfg(char *src)
    {
    save_flags(flags);
    cli();
    src += sizeof(int);
    while (i) {
    if ((ret = copy_from_user((char *) &cfg, src, sizeof(cfg)))) {
    restore_flags(flags);
    return ret;
    }
    restore_flags(flags);
    }
    static int
    isdn_get_allcfg(char *dest)

    the same
    ***************

    Unfortunatly I won't be able to fix these problems but I hope I have
    provided enough hints for the driver maintainers, so that they can fix
    it (maybe they have already done that).

    Jean

    --
    I get up each morning, gather my wits.
    Pick up the paper, read the obits.
    if I'm not there I know I'm not dead.
    So I eat a good breakfast and go back to bed. Peete Seeger

    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.rutgers.edu

    \
     
     \ /
      Last update: 2005-03-22 13:42    [W:0.033 / U:0.324 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site