apply accumulated post 1.8.0 fixes, bump version to 1.8.1 1_8_1
authorDenis Vlasenko <vda.linux@googlemail.com>
Sat, 10 Nov 2007 02:01:51 +0000 (02:01 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Sat, 10 Nov 2007 02:01:51 +0000 (02:01 -0000)
Makefile
archival/unzip.c
loginutils/login.c
modutils/modprobe.c
networking/telnetd.c
scripts/defconfig
sysklogd/syslogd.c

index 6587d901eea225ff4221b99da238cbd94c341a2c..b2ce6d4939e670d649c324be3edbc5aae085a9bb 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 8
-SUBLEVEL = 0
+SUBLEVEL = 1
 EXTRAVERSION =
 NAME = Unnamed
 
index 56a5eb625a2e05f8061ab4f91aaf42feaabd1a3b..8462822f1a1529fc1f5277ba6ea9e79fc60f344c 100644 (file)
@@ -41,8 +41,10 @@ enum {
 #endif
 };
 
+#define ZIP_HEADER_LEN 26
+
 typedef union {
-       uint8_t raw[26];
+       uint8_t raw[ZIP_HEADER_LEN];
        struct {
                uint16_t version;                       /* 0-1 */
                uint16_t flags;                         /* 2-3 */
@@ -57,8 +59,14 @@ typedef union {
        } formatted ATTRIBUTE_PACKED;
 } zip_header_t;
 
+/* Check the offset of the last element, not the length.  This leniency
+ * allows for poor packing, whereby the overall struct may be too long,
+ * even though the elements are all in the right place.
+ */
 struct BUG_zip_header_must_be_26_bytes {
-       char BUG_zip_header_must_be_26_bytes[sizeof(zip_header_t) == 26 ? 1 : -1];
+       char BUG_zip_header_must_be_26_bytes[
+               offsetof(zip_header_t, formatted.extra_len) + 2 ==
+                       ZIP_HEADER_LEN ? 1 : -1];
 };
 
 #define FIX_ENDIANNESS(zip_header) do { \
@@ -256,7 +264,7 @@ int unzip_main(int argc, char **argv)
                        bb_error_msg_and_die("invalid zip magic %08X", magic);
 
                /* Read the file header */
-               xread(src_fd, zip_header.raw, sizeof(zip_header));
+               xread(src_fd, zip_header.raw, ZIP_HEADER_LEN);
                FIX_ENDIANNESS(zip_header);
                if ((zip_header.formatted.method != 0) && (zip_header.formatted.method != 8)) {
                        bb_error_msg_and_die("unsupported method %d", zip_header.formatted.method);
index bddc0f533886971b2dc62942a462745039c26d77..53d3e528ba6b059df329462787e5f746455fd8d0 100644 (file)
@@ -239,9 +239,14 @@ int login_main(int argc, char **argv)
        char full_tty[TTYNAME_SIZE];
        USE_SELINUX(security_context_t user_sid = NULL;)
        USE_FEATURE_UTMP(struct utmp utent;)
-       USE_PAM(pam_handle_t *pamh;)
-       USE_PAM(int pamret;)
-       USE_PAM(const char *failed_msg;)
+#if ENABLE_PAM
+       int pamret;
+       pam_handle_t *pamh;
+       const char *pamuser;
+       const char *failed_msg;
+       struct passwd pwdstruct;
+       char pwdbuf[256];
+#endif
 
        short_tty = full_tty;
        username[0] = '\0';
@@ -297,18 +302,18 @@ int login_main(int argc, char **argv)
 #if ENABLE_PAM
                pamret = pam_start("login", username, &conv, &pamh);
                if (pamret != PAM_SUCCESS) {
-                       failed_msg = "pam_start";
+                       failed_msg = "start";
                        goto pam_auth_failed;
                }
                /* set TTY (so things like securetty work) */
                pamret = pam_set_item(pamh, PAM_TTY, short_tty);
                if (pamret != PAM_SUCCESS) {
-                       failed_msg = "pam_set_item(TTY)";
+                       failed_msg = "set_item(TTY)";
                        goto pam_auth_failed;
                }
                pamret = pam_authenticate(pamh, 0);
                if (pamret != PAM_SUCCESS) {
-                       failed_msg = "pam_authenticate";
+                       failed_msg = "authenticate";
                        goto pam_auth_failed;
                        /* TODO: or just "goto auth_failed"
                         * since user seems to enter wrong password
@@ -318,28 +323,42 @@ int login_main(int argc, char **argv)
                /* check that the account is healthy */
                pamret = pam_acct_mgmt(pamh, 0);
                if (pamret != PAM_SUCCESS) {
-                       failed_msg = "account setup";
+                       failed_msg = "acct_mgmt";
                        goto pam_auth_failed;
                }
                /* read user back */
-               {
-                       const char *pamuser;
-                       /* gcc: "dereferencing type-punned pointer breaks aliasing rules..."
-                        * thus we cast to (void*) */
-                       if (pam_get_item(pamh, PAM_USER, (void*)&pamuser) != PAM_SUCCESS) {
-                               failed_msg = "pam_get_item(USER)";
-                               goto pam_auth_failed;
-                       }
-                       safe_strncpy(username, pamuser, sizeof(username));
+               pamuser = NULL;
+               /* gcc: "dereferencing type-punned pointer breaks aliasing rules..."
+                * thus we cast to (void*) */
+               if (pam_get_item(pamh, PAM_USER, (void*)&pamuser) != PAM_SUCCESS) {
+                       failed_msg = "get_item(USER)";
+                       goto pam_auth_failed;
                }
-               /* If we get here, the user was authenticated, and is
-                * granted access. */
-               pw = getpwnam(username);
-               if (pw)
-                       break;
-               goto auth_failed;
+               if (!pamuser || !pamuser[0])
+                       goto auth_failed;
+               safe_strncpy(username, pamuser, sizeof(username));
+               /* Don't use "pw = getpwnam(username);",
+                * PAM is said to be capable of destroying static storage
+                * used by getpwnam(). We are using safe(r) function */
+               pw = NULL;
+               getpwnam_r(username, &pwdstruct, pwdbuf, sizeof(pwdbuf), &pw);
+               if (!pw)
+                       goto auth_failed;
+               pamret = pam_open_session(pamh, 0);
+               if (pamret != PAM_SUCCESS) {
+                       failed_msg = "open_session";
+                       goto pam_auth_failed;
+               }
+               pamret = pam_setcred(pamh, PAM_ESTABLISH_CRED);
+               if (pamret != PAM_SUCCESS) {
+                       failed_msg = "setcred";
+                       goto pam_auth_failed;
+               }
+               break; /* success, continue login process */
+
  pam_auth_failed:
-               bb_error_msg("%s failed: %s (%d)", failed_msg, pam_strerror(pamh, pamret), pamret);
+               bb_error_msg("pam_%s call failed: %s (%d)", failed_msg,
+                                       pam_strerror(pamh, pamret), pamret);
                safe_strncpy(username, "UNKNOWN", sizeof(username));
 #else /* not PAM */
                pw = getpwnam(username);
index f7d193a055de96627bf2367ffcb7187f5df575e5..dafbb4ecd7ea9ce0c500458c2a5a913a8dd118fe 100644 (file)
@@ -791,7 +791,7 @@ static void check_dep(char *mod, struct mod_list_t **head, struct mod_list_t **t
        if (*tail)
                (*tail)->m_next = find;
        find->m_prev = *tail;
-       /*find->m_next = NULL; - xzalloc did it */
+       find->m_next = NULL; /* possibly NOT done by xzalloc! */
 
        if (!*head)
                *head = find;
index cccf03dfd54944bd88ff059eab52392117511db5..108bbf44f5770fe085810ab289f3fce7fc8fa550 100644 (file)
@@ -279,6 +279,10 @@ make_new_session(
        /* make new session and process group */
        setsid();
 
+       /* Restore default signal handling */
+       signal(SIGCHLD, SIG_DFL);
+       signal(SIGPIPE, SIG_DFL);
+
        /* open the child's side of the tty. */
        /* NB: setsid() disconnects from any previous ctty's. Therefore
         * we must open child's side of the tty AFTER setsid! */
@@ -302,14 +306,18 @@ make_new_session(
        /* Uses FILE-based I/O to stdout, but does fflush(stdout),
         * so should be safe with vfork.
         * I fear, though, that some users will have ridiculously big
-        * issue files, and they may block writing to fd 1. */
+        * issue files, and they may block writing to fd 1,
+        * (parent is supposed to read it, but parent waits
+        * for vforked child to exec!) */
        print_login_issue(issuefile, NULL);
 
        /* Exec shell / login / whatever */
        login_argv[0] = loginpath;
        login_argv[1] = NULL;
-       execvp(loginpath, (char **)login_argv);
-       /* Safer with vfork, and we shouldn't send message
+       /* exec busybox applet (if PREFER_APPLETS=y), if that fails,
+        * exec external program */
+       BB_EXECVP(loginpath, (char **)login_argv);
+       /* _exit is safer with vfork, and we shouldn't send message
         * to remote clients anyway */
        _exit(1); /*bb_perror_msg_and_die("execv %s", loginpath);*/
 }
@@ -374,7 +382,7 @@ free_session(struct tsession *ts)
 
 #else /* !FEATURE_TELNETD_STANDALONE */
 
-/* Used in main() only, thus exits. */
+/* Used in main() only, thus "return 0" actually is exit(0). */
 #define free_session(ts) return 0
 
 #endif
@@ -384,20 +392,22 @@ static void handle_sigchld(int sig)
        pid_t pid;
        struct tsession *ts;
 
-       pid = waitpid(-1, &sig, WNOHANG);
-       if (pid > 0) {
+       /* Looping: more than one child may have exited */
+       while (1) {
+               pid = waitpid(-1, NULL, WNOHANG);
+               if (pid <= 0)
+                       break;
                ts = sessions;
                while (ts) {
                        if (ts->shell_pid == pid) {
                                ts->shell_pid = -1;
-                               return;
+                               break;
                        }
                        ts = ts->next;
                }
        }
 }
 
-
 int telnetd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int telnetd_main(int argc, char **argv)
 {
@@ -430,7 +440,7 @@ int telnetd_main(int argc, char **argv)
                if (!(opt & OPT_FOREGROUND)) {
                        /* DAEMON_CHDIR_ROOT was giving inconsistent
                         * behavior with/without -F, -i */
-                       bb_daemonize_or_rexec(0 /*DAEMON_CHDIR_ROOT*/, argv);
+                       bb_daemonize_or_rexec(0 /*was DAEMON_CHDIR_ROOT*/, argv);
                }
        }
        /* Redirect log to syslog early, if needed */
@@ -466,6 +476,8 @@ int telnetd_main(int argc, char **argv)
 
        if (opt & OPT_WATCHCHILD)
                signal(SIGCHLD, handle_sigchld);
+       else /* prevent dead children from becoming zombies */
+               signal(SIGCHLD, SIG_IGN);
 
 /*
    This is how the buffers are used. The arrows indicate the movement
@@ -497,7 +509,7 @@ int telnetd_main(int argc, char **argv)
        while (ts) {
                struct tsession *next = ts->next; /* in case we free ts. */
                if (ts->shell_pid == -1) {
-                       /* Child died ad we detected that */
+                       /* Child died and we detected that */
                        free_session(ts);
                } else {
                        if (ts->size1 > 0)       /* can write to pty */
@@ -514,7 +526,7 @@ int telnetd_main(int argc, char **argv)
        if (!IS_INETD) {
                FD_SET(master_fd, &rdfdset);
                /* This is needed because free_session() does not
-                * take into account master_fd when it finds new
+                * take master_fd into account when it finds new
                 * maxfd among remaining fd's */
                if (master_fd > maxfd)
                        maxfd = master_fd;
index 7cd17ec64b02f7c8dc45da742d191f6fcd807f68..5c359a843890edd19d30b90e93e5894f492ad7ac 100644 (file)
@@ -1,5 +1,4 @@
 #
-#
 CONFIG_HAVE_DOT_CONFIG=y
 
 #
@@ -37,10 +36,9 @@ CONFIG_FEATURE_HAVE_RPC=y
 #
 # CONFIG_STATIC is not set
 # CONFIG_BUILD_LIBBUSYBOX is not set
-# CONFIG_FEATURE_FULL_LIBBUSYBOX is not set
+# CONFIG_FEATURE_INDIVIDUAL is not set
 # CONFIG_FEATURE_SHARED_BUSYBOX is not set
 CONFIG_LFS=y
-# CONFIG_BUILD_AT_ONCE is not set
 
 #
 # Debugging Options
@@ -58,7 +56,11 @@ CONFIG_INCLUDE_SUSv2=y
 # CONFIG_INSTALL_NO_USR is not set
 CONFIG_INSTALL_APPLET_SYMLINKS=y
 # CONFIG_INSTALL_APPLET_HARDLINKS is not set
+# CONFIG_INSTALL_APPLET_SCRIPT_WRAPPERS is not set
 # CONFIG_INSTALL_APPLET_DONT is not set
+# CONFIG_INSTALL_SH_APPLET_SYMLINK is not set
+# CONFIG_INSTALL_SH_APPLET_HARDLINK is not set
+# CONFIG_INSTALL_SH_APPLET_SCRIPT_WRAPPER is not set
 CONFIG_PREFIX="./_install"
 
 #
@@ -90,6 +92,7 @@ CONFIG_IOCTL_HEX2STR_ERROR=y
 CONFIG_AR=y
 CONFIG_FEATURE_AR_LONG_FILENAMES=y
 CONFIG_BUNZIP2=y
+CONFIG_BZIP2=y
 CONFIG_CPIO=y
 # CONFIG_DPKG is not set
 # CONFIG_DPKG_DEB is not set
@@ -261,6 +264,7 @@ CONFIG_CHVT=y
 CONFIG_CLEAR=y
 CONFIG_DEALLOCVT=y
 CONFIG_DUMPKMAP=y
+CONFIG_KBD_MODE=y
 CONFIG_LOADFONT=y
 CONFIG_LOADKMAP=y
 CONFIG_OPENVT=y
@@ -465,6 +469,7 @@ CONFIG_FEATURE_MKSWAP_V0=y
 CONFIG_MORE=y
 CONFIG_FEATURE_USE_TERMIOS=y
 CONFIG_MOUNT=y
+CONFIG_FEATURE_MOUNT_HELPERS=y
 CONFIG_FEATURE_MOUNT_NFS=y
 CONFIG_FEATURE_MOUNT_CIFS=y
 CONFIG_FEATURE_MOUNT_FLAGS=y
@@ -549,6 +554,7 @@ CONFIG_FTPPUT=y
 CONFIG_FEATURE_FTPGETPUT_LONG_OPTIONS=y
 CONFIG_HOSTNAME=y
 CONFIG_HTTPD=y
+CONFIG_FEATURE_HTTPD_RANGES=y
 CONFIG_FEATURE_HTTPD_USE_SENDFILE=y
 # CONFIG_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP is not set
 # CONFIG_FEATURE_HTTPD_SETUID is not set
@@ -560,6 +566,7 @@ CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR=y
 CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV=y
 CONFIG_FEATURE_HTTPD_ENCODE_URL_STR=y
 CONFIG_FEATURE_HTTPD_ERROR_PAGES=y
+CONFIG_FEATURE_HTTPD_PROXY=y
 CONFIG_IFCONFIG=y
 CONFIG_FEATURE_IFCONFIG_STATUS=y
 CONFIG_FEATURE_IFCONFIG_SLIP=y
@@ -589,6 +596,7 @@ CONFIG_FEATURE_IP_ROUTE=y
 CONFIG_FEATURE_IP_TUNNEL=y
 CONFIG_FEATURE_IP_RULE=y
 CONFIG_FEATURE_IP_SHORT_FORMS=y
+CONFIG_FEATURE_IP_RARE_PROTOCOLS=y
 CONFIG_IPADDR=y
 CONFIG_IPLINK=y
 CONFIG_IPROUTE=y
@@ -647,9 +655,11 @@ CONFIG_KILL=y
 CONFIG_KILLALL=y
 CONFIG_KILLALL5=y
 CONFIG_NMETER=y
+CONFIG_PGREP=y
 CONFIG_PIDOF=y
 CONFIG_FEATURE_PIDOF_SINGLE=y
 CONFIG_FEATURE_PIDOF_OMIT=y
+CONFIG_PKILL=y
 CONFIG_PS=y
 CONFIG_FEATURE_PS_WIDE=y
 CONFIG_RENICE=y
@@ -658,6 +668,7 @@ CONFIG_TOP=y
 CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE=y
 CONFIG_FEATURE_TOP_CPU_GLOBAL_PERCENTS=y
 # CONFIG_FEATURE_TOP_DECIMALS is not set
+CONFIG_FEATURE_TOPMEM=y
 CONFIG_UPTIME=y
 CONFIG_WATCH=y
 
@@ -743,6 +754,7 @@ CONFIG_SOFTLIMIT=y
 # CONFIG_SETENFORCE is not set
 # CONFIG_SETFILES is not set
 # CONFIG_FEATURE_SETFILES_CHECK_OPTION is not set
+# CONFIG_SETSEBOOL is not set
 
 #
 # ipsvd utilities
index ba46792b6e6401ec19a0a3acfe33091be452b445..da63ced4261a25cca5d59fea09aadb38843845af 100644 (file)
@@ -381,8 +381,8 @@ static void parse_fac_prio_20(int pri, char *res20)
 }
 
 /* len parameter is used only for "is there a timestamp?" check.
- * NB: some callers cheat and supply 0 when they know
- * that there is no timestamp, short-cutting the test. */
+ * NB: some callers cheat and supply len==0 when they know
+ * that there is no timestamp, short-circuiting the test. */
 static void timestamp_and_log(int pri, char *msg, int len)
 {
        char *timestamp;
@@ -427,10 +427,10 @@ static void split_escape_and_log(char *tmpbuf, int len)
                if (*p == '<') {
                        /* Parse the magic priority number */
                        pri = bb_strtou(p + 1, &p, 10);
-                       if (*p == '>') p++;
-                       if (pri & ~(LOG_FACMASK | LOG_PRIMASK)) {
+                       if (*p == '>')
+                               p++;
+                       if (pri & ~(LOG_FACMASK | LOG_PRIMASK))
                                pri = (LOG_USER | LOG_NOTICE);
-                       }
                }
 
                while ((c = *p++)) {
@@ -526,14 +526,32 @@ static void do_syslogd(void)
 
        for (;;) {
                size_t sz;
-
+ read_again:
                sz = safe_read(sock_fd, G.recvbuf, MAX_READ - 1);
-               if (sz <= 0) {
-                       //if (sz == 0)
-                       //      continue; /* EOF from unix socket??? */
+               if (sz < 0) {
                        bb_perror_msg_and_die("read from /dev/log");
                }
 
+               /* Drop trailing NULs (typically there is one NUL) */
+               while (1) {
+                       if (sz == 0)
+                               goto read_again;
+                       /* man 3 syslog says: "A trailing newline is added when needed".
+                        * However, neither glibc nor uclibc do this:
+                        * syslog(prio, "test")   sends "test\0" to /dev/log,
+                        * syslog(prio, "test\n") sends "test\n\0",
+                        * IOW: newline is passed verbatim!
+                        * I take it to mean that it's syslogd's job
+                        * to make those look identical in the log files */
+                       if (G.recvbuf[sz-1] && G.recvbuf[sz-1] != '\n')
+                               break;
+                       sz--;
+               }
+               /* Maybe we need to add '\n' here, not later?
+                * It looks like stock syslogd does send '\n' over network,
+                * but we do not (see sendto below) */
+               G.recvbuf[sz] = '\0'; /* make sure it *is* NUL terminated */
+
                /* TODO: maybe suppress duplicates? */
 #if ENABLE_FEATURE_REMOTE_LOG
                /* We are not modifying log messages in any way before send */
@@ -549,7 +567,6 @@ static void do_syslogd(void)
                        }
                }
 #endif
-               G.recvbuf[sz] = '\0';
                split_escape_and_log(G.recvbuf, sz);
        } /* for */
 }