KDE-3.5.10 hangs on startup!

Andreas Haumer andreas at xss.co.at
Fri Aug 29 17:57:46 BST 2008


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi!

(I already posted this to kde-devel, but got the hint to
better post it to kde-core-devel)

After upgrade from kde-3.5.9 to kde-3.5.10 I found that
the startup sequence as executed by startkde hangs!

After login using KDM and kdm_greeter I see the following processes:

andreas   2695  0.4  0.0   1972  1028 ?        Ss   22:22   0:00 /bin/sh /opt/kde3/bin/startkde
andreas   2737  1.3  0.6  26584 12908 ?        S    22:22   0:00 ksplash --nodcop
andreas   2739  0.7  0.3  22900  7872 ?        S    22:22   0:00 /opt/kde3/bin/kdeinit --oom-pipe 4 --new-startup +kcminit_startup
andreas   2740  0.0  0.0      0     0 ?        Z    22:22   0:00 [start_kdeinit_w] <defunct>
root      2741  0.0  0.0   1188   280 ?        S    22:22   0:00 start_kdeinit --new-startup +kcminit_startup
andreas   2742  0.0  0.4  22908  8536 ?        Ss   22:22   0:00 /opt/kde3/bin/kdeinit --oom-pipe 4 --new-startup +kcminit_startup
andreas   2743  0.0  0.4  22908  8536 ?        S    22:22   0:00 /opt/kde3/bin/kdeinit --oom-pipe 4 --new-startup +kcminit_startup


If I send a SIGUSR1 to the last process (PID 2743) it get's
one step furter:

andreas   2695  0.0  0.0   1972  1028 ?        Ss   22:22   0:00 /bin/sh /opt/kde3/bin/startkde
andreas   2739  0.0  0.3  22900  7872 ?        S    22:22   0:00 /opt/kde3/bin/kdeinit --oom-pipe 4 --new-startup +kcminit_startup
andreas   2740  0.0  0.0      0     0 ?        Z    22:22   0:00 [start_kdeinit_w] <defunct>
root      2741  0.0  0.0   1188   280 ?        S    22:22   0:00 start_kdeinit --new-startup +kcminit_startup
andreas   2742  0.0  0.4  23448  8820 ?        Ss   22:22   0:00 /opt/kde3/bin/kdeinit --oom-pipe 4 --new-startup +kcminit_startup
andreas   2750  0.0  0.4  23012  8996 ?        S    22:24   0:00 kdeinit: dcopserver --nosid
andreas   2752  0.0  0.4  23448  8820 ?        S    22:24   0:00 /opt/kde3/bin/kdeinit --oom-pipe 4 --new-startup +kcminit_startup


If I repeat sending the waiting processes a SIGUSR I eventuelly
get a initialized KDE desktop...

2695 ?        Ss     0:00 /bin/sh /opt/kde3/bin/startkde
2741 ?        S      0:00 start_kdeinit --new-startup +kcminit_startup
2742 ?        Ss     0:00 kdeinit Running...
2750 ?        S      0:00 kdeinit: dcopserver --nosid
2752 ?        S      0:00 kdeinit: klauncher --new-startup
2758 ?        S      0:00 kdeinit: kded --new-startup
2765 ?        S      0:00 kdeinit: kcminit_startup
2766 ?        S      0:00 kwrapper ksmserver
2767 ?        S      0:00 kdeinit Running...


It looks like the changes to start_kdeinit.c (from kdelibs)
triggered this behaviour. It seems, the OOM protection doesn't
work right so that all starting processes are hanging in the
reset_oom_protect() method waiting for a SIGUSR1 signal to
come.

The problem is: this signal should be sent by the main method
of start_kdeinit (look at the end, the code which get's executed
by the child process):

~      case 0: /* child, keep privileges and do the privileged work */
~         close( pipes[ 1 ] );
~         for(;;) {
~            pid_t pid = 0;
~            int ret = read( pipes[ 0 ], &pid, sizeof( pid_t ));
~            if( ret < 0 && errno == EINTR )
~               continue;
~            if( ret <= 0 ) /* pipe closed or error, exit */
~               _exit(0);
~            if( pid != 0 ) {
~                if (set_protection( pid, 0 ))
~                    kill( pid, SIGUSR1 );
~            }
~         }


The changes from kde 3.5.9 to 3.5.10 makes that signal only be
sent if set_protection() returns a value other than 0:

@@ -145,10 +148,10 @@ int main(int argc, char **argv)
~             if( ret < 0 && errno == EINTR )
~                continue;
~             if( ret <= 0 ) /* pipe closed or error, exit */
- -               return 0;
+               _exit(0);
~             if( pid != 0 ) {
- -                set_protection( pid, 0 );
- -                kill( pid, SIGUSR1 );
+                if (set_protection( pid, 0 ))
+                    kill( pid, SIGUSR1 );
~             }
~          }


But look at this:

static int set_protection( pid_t pid, int enable )
{
~   char buf[ 1024 ];
~   int procfile;
~   sprintf( buf, "/proc/%d/oom_adj", pid );
~   if( !enable ) {
~       /* Be paranoid and check that the pid we got from the pipe
~          belongs to this user. */
~       struct stat st;
~       if( lstat( buf, &st ) < 0 || st.st_uid != getuid())
~           return 0;
~   }
~   procfile = open( buf, O_WRONLY );
~   if( procfile >= 0 ) {
~      if( enable )
~         write( procfile, "-5", sizeof( "-5" ));
~      else
~         write( procfile, "0", sizeof( "0" ));
~      close( procfile );
~   }
~   return 1;
}


In my case, set_protection() will always return 0, because
I'm running Linux 2.4 and I do not have the "/proc/%d/oom_adj"
file!

This change in kde 3.5.10 seems to break KDE on older Linux
systems!

Some testing proves my theory: the hangs are due to patches
introduced to start_kdeinit.c by user "mueller" with SVN
revision #801222 at Apr 25th, 2008.

The corresponding log message says:

"fix CVE-2008-1671: integer overflows and arbitrary
process kill vulnerability"


The following change to start_kedinit.c from kdelibs-3.5.10
makes the startup sequence work again:

- --- kdelibs3/kinit/start_kdeinit.c      19 Aug 2008 18:18:12 -0000      1.1.1.3
+++ kdelibs3/kinit/start_kdeinit.c      29 Aug 2008 10:42:15 -0000
@@ -150,8 +150,8 @@
~             if( ret <= 0 ) /* pipe closed or error, exit */
~                _exit(0);
~             if( pid != 0 ) {
- -                if (set_protection( pid, 0 ))
- -                    kill( pid, SIGUSR1 );
+             set_protection( pid, 0 );
+             kill( pid, SIGUSR1 );
~             }
~          }
~    }



Note: this is IMHO not the correct and final fix to solve the
problem, it's merely a prove that my initial theory is correct.
The original patch tried to change the behaviour of start_kdeinit.c
to *not* send a SIGUSR1 signal to just any PID written through a
pipe to the kdeinit process. The original patch is a security patch!

Alas, it breaks things for older Linux kernels, so it should be improved
in a way which fixes the security problem but also works with Linux-2.4!

Comments?

- - andreas

- --
Andreas Haumer                     | mailto:andreas at xss.co.at
*x Software + Systeme              | http://www.xss.co.at/
Karmarschgasse 51/2/20             | Tel: +43-1-6060114-0
A-1100 Vienna, Austria             | Fax: +43-1-6060114-71

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAki4KoMACgkQxJmyeGcXPhG5zwCbB6mhRecTp7HDWX4aR5b8BIcZ
9b4AnAu4XerA3cbGxKmoi1NLZT/h40p5
=K3D5
-----END PGP SIGNATURE-----




More information about the kde-core-devel mailing list