From mboxrd@z Thu Jan 1 00:00:00 1970 From: md@Linux.IT (Marco d'Itri) Date: Wed, 23 Sep 2009 15:30:59 +0000 Subject: Bug#524940: module-init-tools: modprobe starts fork-bombing on Message-Id: <20090923153059.GA17526@bongo.bofh.it> MIME-Version: 1 Content-Type: multipart/mixed; boundary="IS0zKkzwUGydFO0o" List-Id: To: linux-hotplug@vger.kernel.org --IS0zKkzwUGydFO0o Content-Type: text/plain; charset=us-ascii Content-Disposition: inline -- ciao, Marco --IS0zKkzwUGydFO0o Content-Type: message/rfc822 Content-Disposition: inline Return-Path: X-Original-To: md@wonderland.linux.it Delivered-To: md@wonderland.linux.it Received: from attila.bofh.it (localhost [127.0.0.1]) by bongo.bofh.it (Postfix) with ESMTP id 5D2ED5360 for ; Sun, 20 Sep 2009 16:43:53 +0200 (CEST) Received: from picard.linux.it (picard.linux.it [IPv6:2001:1418:10:5::2]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by attila.bofh.it (Postfix) with ESMTPS id A14545F800 for ; Sun, 20 Sep 2009 16:43:19 +0200 (CEST) Received: from rietz.debian.org (rietz.debian.org [140.211.166.43]) by picard.linux.it (Postfix) with ESMTP id 9BDD71104B for ; Sun, 20 Sep 2009 16:43:17 +0200 (CEST) Received: from debbugs by rietz.debian.org with local (Exim 4.63) (envelope-from ) id 1MpNZC-0006Y2-NL; Sun, 20 Sep 2009 14:39:06 +0000 X-Loop: owner@bugs.debian.org Subject: Bug#524940: module-init-tools: modprobe starts fork-bombing on executing oss-compat Reply-To: Modestas Vainius , 524940@bugs.debian.org Resent-From: Modestas Vainius Resent-To: debian-bugs-dist@lists.debian.org Resent-CC: Marco d'Itri X-Loop: owner@bugs.debian.org Resent-Date: Sun, 20 Sep 2009 14:39:05 +0000 Resent-Message-ID: X-Debian-PR-Message: followup 524940 X-Debian-PR-Package: module-init-tools X-Debian-PR-Keywords: upstream help X-Debian-PR-Source: module-init-tools Received: via spool by 524940-submit@bugs.debian.org id=B524940.125345652924044 (code B ref 524940); Sun, 20 Sep 2009 14:39:05 +0000 Received: (at 524940) by bugs.debian.org; 20 Sep 2009 14:22:09 +0000 X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on picard.linux.it X-Spam-Level: X-Spam-Bayes: score:0.0000 Tokens: new, 136; hammy, 145; neutral, 217; spammy, 6. spammytokens:0.997-1--ANYTHING, 0.995-1--bomb, 0.989-+--fifth, 0.987-1--H*r:sk:1MpNIf-, 0.987-1--HX-Spam-Relays-External:sk:1MpNIf- hammytokens:0.000-+--H*c:sk:pgp-sha, 0.000-+--H*c:protocol, 0.000-+--H*c:micalg, 0.000-+--H*c:signed, 0.000-+--H*c:pgp-signature X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=disabled version=3.2.5 Received: from lan-84-240-22-131.vln.skynet.lt ([84.240.22.131] helo=ozas.sytes.net) by rietz.debian.org with esmtp (Exim 4.63) (envelope-from ) id 1MpNIm-0006CP-Bq; Sun, 20 Sep 2009 14:22:09 +0000 Received: from mdxdesktop.ozas.sytes.net ([192.168.0.6]) by ozas.sytes.net with esmtp (Exim 4.63) (envelope-from ) id 1MpNIf-0002GV-LA; Sun, 20 Sep 2009 17:22:01 +0300 Received: from localhost ([127.0.0.1] helo=mdxdesktop.localnet) by mdxdesktop.ozas.sytes.net with esmtp (Exim 4.69) (envelope-from ) id 1MpNIR-0001AF-F2; Sun, 20 Sep 2009 17:21:47 +0300 From: Modestas Vainius To: "Marco d'Itri" , 524940@bugs.debian.org Date: Sun, 20 Sep 2009 17:21:42 +0300 User-Agent: KMail/1.12.1 (Linux/2.6.31-rc6-amd64; KDE/4.3.1; x86_64; ; ) MIME-Version: 1.0 Content-Type: multipart/signed; boundary="nextPart6271143.4ht8oZ9i6k"; protocol="application/pgp-signature"; micalg=pgp-sha1 Content-Transfer-Encoding: 7bit Message-Id: <200909201721.47107.modestas@vainius.eu> Resent-Sender: Debian BTS Resent-Date: Sun, 20 Sep 2009 14:39:06 +0000 In-Reply-To: <20090420235650.24671.91343.reportbug@warlock.locknet> --nextPart6271143.4ht8oZ9i6k Content-Type: multipart/mixed; boundary="Boundary-01=_3pjtKSmTiPGh40y" Content-Transfer-Encoding: 7bit --Boundary-01=_3pjtKSmTiPGh40y Content-Type: Text/Plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline tags 524940 - help tags 524940 patch thanks Hello, On tre=C4=8Diadienis 05 Rugpj=C5=ABtis 2009 03:05:06 Marco d'Itri wrote: > On Aug 05, Eli Mackenzie wrote: > > With this bug marked "important", apt-listbugs didn't notify me that > > there was anything wrong with this package. A failure to boot seems to > > fit the "makes unrelated software on the system (or the whole system) > > break" description of "critical" more than "important". >=20 > It only affects a small number of users. > BTW, the upstream maintainer does not appear to have time to investigate > this. Feel free to send patches. The bug can only be reproduced with kernel 2.6.19 or earlier (i.e. the kern= el=20 in etch). If /sys/module/*/initstate (added in 2.6.20) is not present, curr= ent=20 modprobe assumes that the module is not loaded. This triggers recursive "fo= rk=20 bomb" as modprobe keeps trying to load snd-pcm (i.e. keeps executing that=20 custom install command of snd-pcm) again and again. More detailed info abou= t=20 this can be found in the patch headers. To reproduce, either install oss-compat under <=3D 2.6.19 kernel or reboot = to <=3D=20 2.6.19 with oss-compat installed (init=3D/bin/bash may be helpful to get sy= stem=20 bootable in this case). Actually, you need 0002 patch to fix this bug, 0001 is just a safety=20 precaution. Please submit both these patches to upstream. Thanks. =2D-=20 Modestas Vainius --Boundary-01=_3pjtKSmTiPGh40y Content-Type: text/x-patch; charset="UTF-8"; name="0002-Get-module-initstate-from-proc-modules-if-it-is-not-.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="0002-Get-module-initstate-from-proc-modules-if-it-is-not-.patch" =46rom 567f889a3c8d50234abef72b10e3af9312aa808f Mon Sep 17 00:00:00 2001 =46rom: Modestas Vainius Date: Sun, 20 Sep 2009 14:41:48 +0300 Subject: [PATCH 2/2] Get module initstate from /proc/modules if it is not s= upported via sysfs. Get module state from /proc/modules if it is not supported via sysfs. /sys/module/*/initstate is only available since Linux 2.6.20. Current code assumes that module is not in the kernel if initstate attribute is absent. Among other potential problems, this may trigger a "fork bomb" if certain custom "install" sequences are used for the module and/or its dependencies. . The patch adds a fallback to /proc/modules in order to get the module state= if /sys/module/*/initstate attribute is missing. The code is based on the module_in_kernel() function from v3.4). "Fork bombing" side effect of the bug is described in [1]. What's more, handling of module_in_kernel() failures could still be improved in order av= oid similar problems when /sys is not mounted. Currently, if module_in_kernel() fails with -1, modprobe assumes the module is not present in the kernel. 1. http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=3D524940 Signed-off-by: Modestas Vainius =2D-- modprobe.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 49 insertions(+), 3 deletions(-) diff --git a/modprobe.c b/modprobe.c index ec46e0b..06825bd 100644 =2D-- a/modprobe.c +++ b/modprobe.c @@ -537,6 +537,42 @@ static int read_attribute(const char *filename, char *= buf, size_t buflen) return (s =3D=3D NULL) ? -1 : 1; } =20 +/* Since /sys/module/%s/initstate is only available since 2.6.20, + fallback to /proc/modules to get module state on earlier kernels. + 0 means module is not live, 1 means yes, -1 means unknown. + */ +static int proc_is_module_live(const char *modname) +{ + FILE *proc_modules; + char *line; + int i, ret; + + /* Might not be mounted yet. Don't fail. */ + proc_modules =3D fopen("/proc/modules", "r"); + if (!proc_modules) + return -1; + + while ((line =3D getline_wrapped(proc_modules, NULL)) !=3D NULL) { + char *entry =3D strtok(line, " \n"); + + if (entry && streq(entry, modname)) { + /* If it exists, initstate is the fifth entry. */ + for (i =3D 1; i < 5; i++) { + if (!(entry =3D strtok(NULL, " \n"))) + break; + } + ret =3D !(entry && (streq(entry, "Loading") || streq(entry, "Unloading"= ))); + + free(line); + fclose(proc_modules); + return ret; + } + free(line); + } + fclose(proc_modules); + return 0; +} + /* Is module in /sys/module? If so, fill in usecount if not NULL.=20 0 means no, 1 means yes, -1 means unknown. */ @@ -562,10 +598,20 @@ static int module_in_kernel(const char *modname, unsi= gned int *usecount) =20 /* Wait for the existing module to either go live or disappear. */ nofail_asprintf(&name, "/sys/module/%s/initstate", modname); + ret =3D 1; while (1) { =2D ret =3D read_attribute(name, attr, ATTR_LEN); =2D if (ret !=3D 1 || streq(attr, "live\n")) =2D break; + /* If ret =3D=3D 0 upon second and subsequent cycles, + /sys/module/%s/initstate is not supported. Do not try again. */ + if (ret !=3D 0) + ret =3D read_attribute(name, attr, ATTR_LEN); + if (ret =3D=3D 1) { + if (streq(attr, "live\n")) + break; + } else { + ret =3D proc_is_module_live(modname); + if (ret !=3D 0) + break; + } =20 usleep(100000); } =2D-=20 1.6.4.3 --Boundary-01=_3pjtKSmTiPGh40y Content-Type: text/x-patch; charset="UTF-8"; name="0001-Ignore-custom-install-commands-if-failed-to-find-whe.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="0001-Ignore-custom-install-commands-if-failed-to-find-whe.patch" =46rom 47a0c951d41f586f4e8dfeef3e770449a0fb2570 Mon Sep 17 00:00:00 2001 =46rom: Modestas Vainius Date: Sun, 20 Sep 2009 16:15:44 +0300 Subject: [PATCH 1/2] Ignore custom install commands if failed to find wheth= er module is loaded. This should protect from disastrous consequences like in [1] if for some reason module_in_kernel() status cannot be determined. 1. http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=3D524940 Signed-off-by: Modestas Vainius =2D-- modprobe.c | 16 +++++++++++----- 1 files changed, 11 insertions(+), 5 deletions(-) diff --git a/modprobe.c b/modprobe.c index 21a3111..ec46e0b 100644 =2D-- a/modprobe.c +++ b/modprobe.c @@ -1095,6 +1095,7 @@ static int insmod(struct list_head *list, const char *command; struct module *mod =3D list_entry(list->next, struct module, list); int rc =3D 0; + int isloaded =3D 0; =20 /* Take us off the list. */ list_del(&mod->list); @@ -1122,7 +1123,7 @@ static int insmod(struct list_head *list, =20 /* Don't do ANYTHING if already in kernel. */ if (!(flags & mit_ignore_loaded) =2D && module_in_kernel(newname ?: mod->modname, NULL) =3D=3D 1) { + && (isloaded =3D module_in_kernel(newname ?: mod->modname, NULL) =3D= =3D 1)) { if (flags & mit_first_time) error("Module %s already in kernel.\n", newname ?: mod->modname); @@ -1131,10 +1132,15 @@ static int insmod(struct list_head *list, =20 command =3D find_command(mod->modname, commands); if (command && !(flags & mit_ignore_commands)) { =2D close_file(fd); =2D do_command(mod->modname, command, flags & mit_dry_run, error, =2D "install", cmdline_opts); =2D goto out_optstring; + if (isloaded =3D=3D -1) { + error("Unable to find if module %s is loaded. Assuming --ignore-install= =2E\n", + newname ?: mod->modname); + } else { + close_file(fd); + do_command(mod->modname, command, flags & mit_dry_run, error, + "install", cmdline_opts); + goto out_optstring; + } } =20 module =3D grab_elf_file_fd(mod->filename, fd); =2D-=20 1.6.4.3 --Boundary-01=_3pjtKSmTiPGh40y-- --nextPart6271143.4ht8oZ9i6k Content-Type: application/pgp-signature; name=signature.asc Content-Description: This is a digitally signed message part. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) iEYEABECAAYFAkq2OncACgkQHO9JRnPq4hRUSACfQPo//uNRBXv13SK0qftHG8BF oagAoPVQCfjKAyZ/z9c3xrnHJxargKDg =5sSf -----END PGP SIGNATURE----- --nextPart6271143.4ht8oZ9i6k-- --IS0zKkzwUGydFO0o--