From 1211832977b98c491d1198ab66c4f8ffc0886a87 Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Tue, 22 Jan 2019 12:01:09 +0100 Subject: [PATCH] busybox: handle crypt() errors in loginutils The crypt(3) function is allowed to fail with either EINVAL or ENOSYS when the given salt is either invalid or when the requested algorithm is not implemented. In such a case, libbb's pw_encrypt() function will silently convert the crypt() NULL return value into an empty string which is then processed without further errors by utilities such as chpasswd or passwd, causing them to set an empty password when an unsupported cipher is requested. Patch the relevant users of pw_encrypt() to abort in case an empty hash is returned by pw_encrypt() in order to mitigate the problem. Signed-off-by: Jo-Philipp Wich --- package/utils/busybox/Makefile | 2 +- ...520-loginutils-handle-crypt-failures.patch | 53 +++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 package/utils/busybox/patches/520-loginutils-handle-crypt-failures.patch diff --git a/package/utils/busybox/Makefile b/package/utils/busybox/Makefile index 74dbf84d3b..3969bbeb18 100644 --- a/package/utils/busybox/Makefile +++ b/package/utils/busybox/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=busybox PKG_VERSION:=1.30.0 -PKG_RELEASE:=3 +PKG_RELEASE:=4 PKG_FLAGS:=essential PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 diff --git a/package/utils/busybox/patches/520-loginutils-handle-crypt-failures.patch b/package/utils/busybox/patches/520-loginutils-handle-crypt-failures.patch new file mode 100644 index 0000000000..d44375426f --- /dev/null +++ b/package/utils/busybox/patches/520-loginutils-handle-crypt-failures.patch @@ -0,0 +1,53 @@ +--- a/loginutils/chpasswd.c ++++ b/loginutils/chpasswd.c +@@ -97,6 +97,11 @@ int chpasswd_main(int argc UNUSED_PARAM, + + crypt_make_pw_salt(salt, algo); + free_me = pass = pw_encrypt(pass, salt, 0); ++ ++ if (pass[0] == 0) { ++ free(free_me); ++ bb_perror_msg_and_die("password encryption failed"); ++ } + } + + /* This is rather complex: if user is not found in /etc/shadow, +--- a/loginutils/cryptpw.c ++++ b/loginutils/cryptpw.c +@@ -95,7 +95,7 @@ int cryptpw_main(int argc UNUSED_PARAM, + /* Supports: cryptpw -m sha256 PASS 'rounds=999999999$SALT' */ + char salt[MAX_PW_SALT_LEN + sizeof("rounds=999999999$")]; + char *salt_ptr; +- char *password; ++ char *password, *hash; + const char *opt_m, *opt_S; + int fd; + +@@ -140,8 +140,12 @@ int cryptpw_main(int argc UNUSED_PARAM, + /* may still be NULL on EOF/error */ + } + +- if (password) +- puts(pw_encrypt(password, salt, 1)); ++ if (password) { ++ hash = pw_encrypt(password, salt, 1); ++ if (hash[0] == 0) ++ bb_perror_msg_and_die("password encryption failed"); ++ puts(hash); ++ } + + return EXIT_SUCCESS; + } +--- a/loginutils/passwd.c ++++ b/loginutils/passwd.c +@@ -187,6 +187,10 @@ int passwd_main(int argc UNUSED_PARAM, c + if (!newp) { + logmode = LOGMODE_STDIO; + bb_error_msg_and_die("password for %s is unchanged", name); ++ } else if (newp[0] == 0) { ++ logmode = LOGMODE_STDIO; ++ free(newp); ++ bb_perror_msg_and_die("password encryption failed"); + } + } else if (opt & OPT_lock) { + if (!c) -- 2.30.2