Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
Bug 179255 - utmp corruption with agetty
Summary: utmp corruption with agetty
Status: RESOLVED INVALID
Alias: None
Product: Gentoo Linux
Classification: Unclassified
Component: [OLD] Core system (show other bugs)
Hardware: x86 Linux
: High normal
Assignee: Gentoo's Team for Core System packages
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-05-20 19:25 UTC by Gil Kloepfer
Modified: 2007-06-15 18:42 UTC (History)
0 users

See Also:
Package list:
Runtime testing required: ---


Attachments
Proposed patch to be added to port to address problem (agetty-port-patch,1.02 KB, patch)
2007-05-23 02:53 UTC, Gil Kloepfer
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Gil Kloepfer 2007-05-20 19:25:06 UTC
/var/run/utmp appears to be growing without bounds as agetty is writing duplicate line entries to the bottom of the file even though there is a matching line/id pair in the utmp file for the tty already.

This problem (1) causes utmp to grow without bounds (bad idea) and (2) causes 'uptime' and 'top' (and friends) to report the wrong number of logged-in users.

Using 'who' directly (without specifying a utmp file) does not show the offending entries because it does a kill 0 on the PID in the utmp file by default, and if the PID doesn't exist the entry is not printed (is this behavior really correct?).

Reproducible: Sometimes

Steps to Reproduce:
1. do a who -a /var/run/utmp
2. log onto a virtual console (tty1 .. ttyx)
3. log out
4. see if the number of utmp entries have changed (step 1 again)
5. If this hasn't happened yet, try again on another virtual console

Actual Results:  
Extra entries ended up in utmp:

limbic$ who -a /var/run/utmp
                        May  6 09:39              1597 id=si    term=0 exit=0
           system boot  May  6 09:39
                        May  6 09:39              2761 id=rc    term=0 exit=0
           run-level 3  May  6 09:39                   last=S
                        May  6 09:38              4308 id=l3    term=0 exit=0
                        May 20 13:36             18188 id=c1
                        May 20 13:38             18207 id=c2
                        May 17 19:06             20456 id=c3
LOGIN      tty4         May  6 09:38              5573 id=c4
LOGIN      tty5         May  6 09:38              5574 id=c5
LOGIN      tty6         May  6 09:38              5575 id=c6
gil      + pts/0        May 20 13:44 00:20       18280 (:0.0)
gil      + pts/1        May 20 12:02 00:26       17809 (lap-wl.kloepfer.org)
gil      + pts/2        May 20 14:04   .         18372 (:0.0)
           pts/3        May 19 23:33             15102 id=ts/3  term=0 exit=0
gil      + tty1         May 20 13:44 00:20       18188
           pts/2        May  8 23:45             24836 id=/2    term=0 exit=0
LOGIN      tty1         May  9 07:36             26557 id=1
gil      - tty2         May 20 13:37 00:26       25102
           pts/0        May  9 18:24             29211 id=/0    term=0 exit=0
LOGIN      tty1         May  9 18:25             29224 id=1
LOGIN      tty2         May  9 22:47             30332 id=2
LOGIN      tty1         May 12 23:20             25051 id=1
LOGIN      tty2         May 13 11:10             21360 id=2
LOGIN      tty1         May 17 17:56             19565 id=1
LOGIN      tty3         May 17 19:06             20456 id=3
LOGIN      tty2         May 17 19:43              2798 id=2
LOGIN      tty1         May 19 01:46              9051 id=1
LOGIN      tty2         May 19 08:04             25102 id=2
LOGIN      tty1         May 19 12:00             12267 id=1
           pts/4        May 19 17:15             13719 id=ts/4  term=0 exit=0
LOGIN      tty1         May 20 13:36             18188 id=1
LOGIN      tty2         May 20 13:38             18207 id=2


Expected Results:  
The duplicate tty1 / id=1 and likewise should not exist (they should be overwritten during login/logout).

I looked quite a bit into this and what I think is the problem is that there is an inconsistency between what pututline(3) does, what the manual page for pututline(3) actually says it does, and how agetty uses pututline.

What appears to be happening is that agetty reads the utmp file using getutent(3) and looks for an entry with a matching PID.  If this doesn't happen, it creates a new entry and passes it to pututline(3) for processing.  Under normal conditions, pututline(3) itself searches for a matching utmp entry and replaces it if there is a matching line/inittab_id, and if there is no matching line/inittab_id then it appends a new utmp entry.

The problem is that the glibc 2.5-r2 source for pututline(3) (see login/utmp_file.c) does not rewind the utmp file before looking for a matching entry.  Because agetty reads the utmp file (getutent(3)) prior to doing the pututline(3) call, the file_offset is now somewhere in the middle or at the end of the file.  The match will not happen, and pututline(3) will append a new entry to the utmp file.  Because how far agetty reads will be inconsistent, then the behavior exhibited will also be inconsistent.

The question is whether this is a bug in the operation of pututline(3) in glibc (because the man page doesn't specify that pututline(3) requires that setutent(3) be called again), or a bug in agetty that it needs to call setutent(3) prior to pututline(3).

FWIW:
Portage 2.1.2.2 (default-linux/x86/2006.1, gcc-4.1.1, glibc-2.5-r2, 2.6.20-gentoo-r7 i686)
=================================================================
System uname: 2.6.20-gentoo-r7 i686 Intel(R) Pentium(R) 4 CPU 2.40GHz
Gentoo Base System release 1.12.9
Timestamp of tree: Sat, 12 May 2007 22:20:01 +0000
dev-java/java-config: 1.3.7, 2.0.31-r5
dev-lang/python:     2.4.4-r4
dev-python/pycrypto: 2.0.1-r5
sys-apps/sandbox:    1.2.17
sys-devel/autoconf:  2.13, 2.61
sys-devel/automake:  1.4_p6, 1.5, 1.6.3, 1.7.9-r1, 1.8.5-r3, 1.9.6-r2, 1.10
sys-devel/binutils:  2.16.1-r3
sys-devel/gcc-config: 1.3.16
sys-devel/libtool:   1.5.22
virtual/os-headers:  2.6.17-r2
ACCEPT_KEYWORDS="x86"
AUTOCLEAN="yes"
CBUILD="i686-pc-linux-gnu"
CFLAGS="-O2 -march=pentium-m -pipe"
CHOST="i686-pc-linux-gnu"
CONFIG_PROTECT="/etc /usr/share/X11/xkb /var/bind"
CONFIG_PROTECT_MASK="/etc/env.d /etc/env.d/java/ /etc/gconf /etc/init.d /etc/java-config/vms/ /etc/php/apache2-php5/ext-active/ /etc/php/cgi-php5/ext-active/ /etc/php/cli-php5/ext-active/ /etc/revdep-rebuild /etc/terminfo"
CXXFLAGS="-O2 -march=pentium-m -pipe"
DISTDIR="/sysbuild/portage_overlay/distfiles"
FEATURES="distlocks metadata-transfer sandbox sfperms strict"
GENTOO_MIRRORS="http://distfiles.gentoo.org http://distro.ibiblio.org/pub/linux/distributions/gentoo"
MAKEOPTS="-j2"
PKGDIR="/sysbuild/portage_overlay/packages"
PORTAGE_RSYNC_OPTS="--recursive --links --safe-links --perms --times --compress --force --whole-file --delete --delete-after --stats --timeout=180 --exclude=/distfiles --exclude=/local --exclude=/packages --filter=H_**/files/digest-*"
PORTAGE_TMPDIR="/var/tmp"
PORTDIR="/usr/portage"
PORTDIR_OVERLAY="/sysbuild/portage_overlay"
SYNC="rsync://rsync.namerica.gentoo.org/gentoo-portage"
USE="X berkdb bitmap-fonts cli cracklib crypt dri gdbm gpm iconv isdnlog libg++ midi mmx mmxext ncurses nls nptl nptlonly pam pcre perl ppds pppd python readline reflection session spl sse sse2 ssl tcpd truetype-fonts type1-fonts unicode x86 xorg zlib" ALSA_CARDS="ali5451 als4000 atiixp atiixp-modem bt87x ca0106 cmipci emu10k1 emu10k1x ens1370 ens1371 es1938 es1968 fm801 hda-intel intel8x0 intel8x0m maestro3 trident usb-audio via82xx via82xx-modem ymfpci" ALSA_PCM_PLUGINS="adpcm alaw asym copy dmix dshare dsnoop empty extplug file hooks iec958 ioplug ladspa lfloat linear meter mulaw multi null plug rate route share shm softvol" ELIBC="glibc" INPUT_DEVICES="keyboard mouse evdev" KERNEL="linux" LCD_DEVICES="bayrad cfontz cfontz633 glk hd44780 lb216 lcdm001 mtxorb ncurses text" USERLAND="GNU" VIDEO_CARDS="i810 nv vesa vga dummy fbdev vmware"
Unset:  CTARGET, EMERGE_DEFAULT_OPTS, INSTALL_MASK, LANG, LC_ALL, LDFLAGS, LINGUAS, PORTAGE_COMPRESS, PORTAGE_COMPRESS_FLAGS, PORTAGE_RSYNC_EXTRA_OPTS
Comment 1 Gil Kloepfer 2007-05-23 02:27:37 UTC
Updated summary to more accurately describe actual problem.
Comment 2 Gil Kloepfer 2007-05-23 02:53:40 UTC
Created attachment 120046 [details, diff]
Proposed patch to be added to port to address problem

The attached patch will add a patch to the port to agetty (login-utils 2.12r-r6) to fix the problem, assuming that agetty's usage of pututline() is actually incorrect.  This simply adds a 'setutent()' call before the pututline(&ut); to assure that the utmp file is rewound before searching for and (over)writing the utmp record.
Comment 3 Gil Kloepfer 2007-06-15 18:42:45 UTC
After further work with the fix I provided, I discovered that the problem is not due to problems with agetty, and the analysis of the problem I reported was incorrect.

There is a problem involving utmp, but the problem is not with agetty, but rather a race condition in init.  This bug should be reopened (after I first check to make sure that I didn't make the same mistakes as I did in this report) as a bug in init rather than in agetty.