[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#670993: busybox: Please use dpkg-buildflags for hardening support



Michael Tokarev wrote:

> That's the constructs like this:
>
>   bb_error_msg_and_die(bb_msg_memory_exhausted);
>
> where bb_msg_memory_exhausted is declared as extern char *.
> This is a poor-man implementation of internal constant
> string folding done by gcc for years.

How about this patch?  It fixes a few bugs, if I understand correctly
(for example, "stat -Z <string with % signs in it>" passes that string
to vasprintf, allowing privilege escalation if a privileged script
uses a user-specified string in that argument).  I fear it would
increase the text size, though.

A better patch might involve introducing a separate

	bb_error_msgf

function for callers that want to pass a format and letting
bb_error_msg take a simple string, or turning bb_msg_memory_exhausted
et al into string literals as you suggested.

Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
---
 archival/bzip2.c                              |    2 +-
 archival/gzip.c                               |    2 +-
 archival/libarchive/data_extract_to_command.c |    2 +-
 archival/libarchive/decompress_gunzip.c       |    2 +-
 archival/libarchive/decompress_uncompress.c   |    2 +-
 archival/libarchive/decompress_unxz.c         |    2 +-
 coreutils/df.c                                |    2 +-
 coreutils/echo.c                              |    2 +-
 coreutils/expand.c                            |    2 +-
 coreutils/od_bloaty.c                         |    4 ++--
 coreutils/stat.c                              |    4 ++--
 coreutils/tail.c                              |    2 +-
 coreutils/tr.c                                |    2 +-
 coreutils/uudecode.c                          |    2 +-
 coreutils/uuencode.c                          |    2 +-
 editors/sed.c                                 |    2 +-
 libbb/copyfd.c                                |    4 ++--
 libbb/create_icmp6_socket.c                   |    4 ++--
 libbb/create_icmp_socket.c                    |    4 ++--
 libbb/dump.c                                  |   10 ++++++++--
 libbb/fflush_stdout_and_exit.c                |    2 +-
 libbb/mtab.c                                  |    4 ++--
 libbb/wfopen.c                                |    2 +-
 libbb/xfuncs_printf.c                         |   12 ++++++------
 loginutils/addgroup.c                         |    2 +-
 loginutils/adduser.c                          |    2 +-
 loginutils/chpasswd.c                         |    2 +-
 loginutils/deluser.c                          |    2 +-
 loginutils/getty.c                            |    2 +-
 miscutils/crontab.c                           |    2 +-
 miscutils/rx.c                                |    2 +-
 networking/ntpd.c                             |    2 +-
 networking/ntpd_simple.c                      |    2 +-
 networking/ping.c                             |    2 +-
 networking/tcpudp.c                           |    2 +-
 networking/traceroute.c                       |    2 +-
 networking/udhcp/arpping.c                    |    2 +-
 networking/wget.c                             |    4 ++--
 networking/zcip.c                             |    2 +-
 shell/ash.c                                   |    2 +-
 shell/hush.c                                  |    4 ++--
 sysklogd/logread.c                            |    2 +-
 util-linux/fdformat.c                         |    2 +-
 util-linux/mount.c                            |   18 +++++++++---------
 44 files changed, 72 insertions(+), 66 deletions(-)

diff --git i/archival/bzip2.c w/archival/bzip2.c
index dd77c8ef..3845c8c9 100644
--- i/archival/bzip2.c
+++ w/archival/bzip2.c
@@ -127,7 +127,7 @@ IF_DESKTOP(long long) int FAST_FUNC compressStream(transformer_aux_data_t *aux U
 	while (1) {
 		count = full_read(STDIN_FILENO, rbuf, IOBUF_SIZE);
 		if (count < 0) {
-			bb_perror_msg(bb_msg_read_error);
+			bb_perror_msg("%s", bb_msg_read_error);
 			total = -1;
 			break;
 		}
diff --git i/archival/gzip.c w/archival/gzip.c
index 80db4f96..787cf489 100644
--- i/archival/gzip.c
+++ w/archival/gzip.c
@@ -63,7 +63,7 @@ aa:      85.1% -- replaced with aa.gz
 //#define DEBUG 1
 /* Diagnostic functions */
 #ifdef DEBUG
-#  define Assert(cond,msg) { if (!(cond)) bb_error_msg(msg); }
+#  define Assert(cond,msg) { if (!(cond)) bb_error_msg("%s", msg); }
 #  define Trace(x) fprintf x
 #  define Tracev(x) {if (verbose) fprintf x; }
 #  define Tracevv(x) {if (verbose > 1) fprintf x; }
diff --git i/archival/libarchive/data_extract_to_command.c w/archival/libarchive/data_extract_to_command.c
index a2ce33b5..354e9580 100644
--- i/archival/libarchive/data_extract_to_command.c
+++ w/archival/libarchive/data_extract_to_command.c
@@ -38,7 +38,7 @@ static const char *const tar_var[] = {
 static void xputenv(char *str)
 {
 	if (putenv(str))
-		bb_error_msg_and_die(bb_msg_memory_exhausted);
+		bb_error_msg_and_die("%s", bb_msg_memory_exhausted);
 }
 
 static void str2env(char *env[], int idx, const char *str)
diff --git i/archival/libarchive/decompress_gunzip.c w/archival/libarchive/decompress_gunzip.c
index 2d5ab3eb..e249c360 100644
--- i/archival/libarchive/decompress_gunzip.c
+++ w/archival/libarchive/decompress_gunzip.c
@@ -1069,7 +1069,7 @@ static int top_up(STATE_PARAM unsigned n)
 		bytebuffer_offset = 0;
 		bytebuffer_size = full_read(gunzip_src_fd, &bytebuffer[count], bytebuffer_max - count);
 		if ((int)bytebuffer_size < 0) {
-			bb_error_msg(bb_msg_read_error);
+			bb_error_msg("%s", bb_msg_read_error);
 			return 0;
 		}
 		bytebuffer_size += count;
diff --git i/archival/libarchive/decompress_uncompress.c w/archival/libarchive/decompress_uncompress.c
index e9bbfb9b..e333e794 100644
--- i/archival/libarchive/decompress_uncompress.c
+++ w/archival/libarchive/decompress_uncompress.c
@@ -167,7 +167,7 @@ unpack_Z_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd)
 		if (insize < (int) (IBUFSIZ + 64) - IBUFSIZ) {
 			rsize = safe_read(src_fd, inbuf + insize, IBUFSIZ);
 			if (rsize < 0)
-				bb_error_msg_and_die(bb_msg_read_error);
+				bb_error_msg_and_die("%s", bb_msg_read_error);
 			insize += rsize;
 		}
 
diff --git i/archival/libarchive/decompress_unxz.c w/archival/libarchive/decompress_unxz.c
index 79b48a15..a860669a 100644
--- i/archival/libarchive/decompress_unxz.c
+++ w/archival/libarchive/decompress_unxz.c
@@ -69,7 +69,7 @@ unpack_xz_stream(transformer_aux_data_t *aux, int src_fd, int dst_fd)
 		if (iobuf.in_pos == iobuf.in_size) {
 			int rd = safe_read(src_fd, membuf, BUFSIZ);
 			if (rd < 0) {
-				bb_error_msg(bb_msg_read_error);
+				bb_error_msg("%s", bb_msg_read_error);
 				total = -1;
 				break;
 			}
diff --git i/coreutils/df.c w/coreutils/df.c
index 63dbd61b..e6fbf416 100644
--- i/coreutils/df.c
+++ w/coreutils/df.c
@@ -142,7 +142,7 @@ int df_main(int argc UNUSED_PARAM, char **argv)
 	if (!argv[0]) {
 		mount_table = setmntent(bb_path_mtab_file, "r");
 		if (!mount_table)
-			bb_perror_msg_and_die(bb_path_mtab_file);
+			bb_perror_msg_and_die("%s", bb_path_mtab_file);
 	}
 
 	while (1) {
diff --git i/coreutils/echo.c w/coreutils/echo.c
index 9663894e..c70d30ff 100644
--- i/coreutils/echo.c
+++ w/coreutils/echo.c
@@ -171,7 +171,7 @@ int echo_main(int argc UNUSED_PARAM, char **argv)
 	/*r =*/ full_write(STDOUT_FILENO, buffer, out - buffer);
 	free(buffer);
 	if (/*WRONG:r < 0*/ errno) {
-		bb_perror_msg(bb_msg_write_error);
+		bb_perror_msg("%s", bb_msg_write_error);
 		return 1;
 	}
 	return 0;
diff --git i/coreutils/expand.c w/coreutils/expand.c
index 25bbffc6..ac5ad5b2 100644
--- i/coreutils/expand.c
+++ w/coreutils/expand.c
@@ -227,7 +227,7 @@ int expand_main(int argc UNUSED_PARAM, char **argv)
 	/* Now close stdin also */
 	/* (if we didn't read from it, it's a no-op) */
 	if (fclose(stdin))
-		bb_perror_msg_and_die(bb_msg_standard_input);
+		bb_perror_msg_and_die("%s", bb_msg_standard_input);
 
 	fflush_stdout_and_exit(exit_status);
 }
diff --git i/coreutils/od_bloaty.c w/coreutils/od_bloaty.c
index 347f879d..e542a9f6 100644
--- i/coreutils/od_bloaty.c
+++ w/coreutils/od_bloaty.c
@@ -514,7 +514,7 @@ check_and_close(void)
 	}
 
 	if (ferror(stdout)) {
-		bb_error_msg_and_die(bb_msg_write_error);
+		bb_error_msg_and_die("%s", bb_msg_write_error);
 	}
 }
 
@@ -1378,7 +1378,7 @@ int od_main(int argc UNUSED_PARAM, char **argv)
 		dump(n_bytes_to_skip, end_offset);
 
 	if (fclose(stdin))
-		bb_perror_msg_and_die(bb_msg_standard_input);
+		bb_perror_msg_and_die("%s", bb_msg_standard_input);
 
 	return exit_code;
 }
diff --git i/coreutils/stat.c w/coreutils/stat.c
index 2797719d..51298e43 100644
--- i/coreutils/stat.c
+++ w/coreutils/stat.c
@@ -436,7 +436,7 @@ static bool do_statfs(const char *filename, const char *format)
 		     : getfilecon(filename, &scontext)
 		    ) < 0
 		) {
-			bb_perror_msg(filename);
+			bb_perror_msg("%s", filename);
 			return 0;
 		}
 	}
@@ -549,7 +549,7 @@ static bool do_stat(const char *filename, const char *format)
 		     : getfilecon(filename, &scontext)
 		    ) < 0
 		) {
-			bb_perror_msg(filename);
+			bb_perror_msg("%s", filename);
 			return 0;
 		}
 	}
diff --git i/coreutils/tail.c w/coreutils/tail.c
index b376ec86..264fdb47 100644
--- i/coreutils/tail.c
+++ w/coreutils/tail.c
@@ -85,7 +85,7 @@ static ssize_t tail_read(int fd, char *buf, size_t count)
 
 	r = full_read(fd, buf, count);
 	if (r < 0) {
-		bb_perror_msg(bb_msg_read_error);
+		bb_perror_msg("%s", bb_msg_read_error);
 		G.exitcode = EXIT_FAILURE;
 	}
 
diff --git i/coreutils/tr.c w/coreutils/tr.c
index e67948a3..a87e908c 100644
--- i/coreutils/tr.c
+++ w/coreutils/tr.c
@@ -319,7 +319,7 @@ int tr_main(int argc UNUSED_PARAM, char **argv)
 			read_chars = safe_read(STDIN_FILENO, str1, TR_BUFSIZ);
 			if (read_chars <= 0) {
 				if (read_chars < 0)
-					bb_perror_msg_and_die(bb_msg_read_error);
+					bb_perror_msg_and_die("%s", bb_msg_read_error);
 				break;
 			}
 			in_index = 0;
diff --git i/coreutils/uudecode.c w/coreutils/uudecode.c
index b298fcb9..f47f916b 100644
--- i/coreutils/uudecode.c
+++ w/coreutils/uudecode.c
@@ -192,7 +192,7 @@ int base64_main(int argc UNUSED_PARAM, char **argv)
 			if (!size)
 				break;
 			if ((ssize_t)size < 0)
-				bb_perror_msg_and_die(bb_msg_read_error);
+				bb_perror_msg_and_die("%s", bb_msg_read_error);
 			/* Encode the buffer we just read in */
 			bb_uuencode(dst_buf, src_buf, size, bb_uuenc_tbl_base64);
 			xwrite(STDOUT_FILENO, dst_buf, 4 * ((size + 2) / 3));
diff --git i/coreutils/uuencode.c w/coreutils/uuencode.c
index 673ef36e..1e53727d 100644
--- i/coreutils/uuencode.c
+++ w/coreutils/uuencode.c
@@ -58,7 +58,7 @@ int uuencode_main(int argc UNUSED_PARAM, char **argv)
 		if (!size)
 			break;
 		if ((ssize_t)size < 0)
-			bb_perror_msg_and_die(bb_msg_read_error);
+			bb_perror_msg_and_die("%s", bb_msg_read_error);
 		/* Encode the buffer we just read in */
 		bb_uuencode(dst_buf, src_buf, size, tbl);
 		bb_putchar('\n');
diff --git i/editors/sed.c w/editors/sed.c
index a2df9316..68972394 100644
--- i/editors/sed.c
+++ w/editors/sed.c
@@ -929,7 +929,7 @@ static void puts_maybe_newline(char *s, FILE *file, char *last_puts_char, char l
 
 	if (ferror(file)) {
 		xfunc_error_retval = 4;  /* It's what gnu sed exits with... */
-		bb_error_msg_and_die(bb_msg_write_error);
+		bb_error_msg_and_die("%s", bb_msg_write_error);
 	}
 	*last_puts_char = lpc;
 }
diff --git i/libbb/copyfd.c w/libbb/copyfd.c
index eda2747f..8559d0a3 100644
--- i/libbb/copyfd.c
+++ w/libbb/copyfd.c
@@ -66,7 +66,7 @@ static off_t bb_full_fd_action(int src_fd, int dst_fd, off_t size)
 			break;
 		}
 		if (rd < 0) {
-			bb_perror_msg(bb_msg_read_error);
+			bb_perror_msg("%s", bb_msg_read_error);
 			break;
 		}
 		/* dst_fd == -1 is a fake, else... */
@@ -74,7 +74,7 @@ static off_t bb_full_fd_action(int src_fd, int dst_fd, off_t size)
 			ssize_t wr = full_write(dst_fd, buffer, rd);
 			if (wr < rd) {
 				if (!continue_on_write_error) {
-					bb_perror_msg(bb_msg_write_error);
+					bb_perror_msg("%s", bb_msg_write_error);
 					break;
 				}
 				dst_fd = -1;
diff --git i/libbb/create_icmp6_socket.c w/libbb/create_icmp6_socket.c
index 368c6902..bdee7a07 100644
--- i/libbb/create_icmp6_socket.c
+++ w/libbb/create_icmp6_socket.c
@@ -26,8 +26,8 @@ int FAST_FUNC create_icmp6_socket(void)
 #endif
 	if (sock < 0) {
 		if (errno == EPERM)
-			bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
-		bb_perror_msg_and_die(bb_msg_can_not_create_raw_socket);
+			bb_error_msg_and_die("%s", bb_msg_perm_denied_are_you_root);
+		bb_perror_msg_and_die("%s", bb_msg_can_not_create_raw_socket);
 	}
 
 	/* drop root privs if running setuid */
diff --git i/libbb/create_icmp_socket.c w/libbb/create_icmp_socket.c
index 58562698..65eea3b9 100644
--- i/libbb/create_icmp_socket.c
+++ w/libbb/create_icmp_socket.c
@@ -25,8 +25,8 @@ int FAST_FUNC create_icmp_socket(void)
 #endif
 	if (sock < 0) {
 		if (errno == EPERM)
-			bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
-		bb_perror_msg_and_die(bb_msg_can_not_create_raw_socket);
+			bb_error_msg_and_die("%s", bb_msg_perm_denied_are_you_root);
+		bb_perror_msg_and_die("%s", bb_msg_can_not_create_raw_socket);
 	}
 
 	/* drop root privs if running setuid */
diff --git i/libbb/dump.c w/libbb/dump.c
index 7e435643..5c30115f 100644
--- i/libbb/dump.c
+++ w/libbb/dump.c
@@ -613,7 +613,13 @@ static void display(priv_dumper_t* dumper)
 							printf(pr->fmt, (char *) bp);
 							break;
 						case F_TEXT:
-							printf(pr->fmt);
+							/*
+							 * pr->fmt has no % signs, so plain
+							 * printf(pr->fmt) would be fine, too
+							 * this more explicit expression is to keep
+							 * gcc -Wformat-security happy
+							 */
+							printf("%s", pr->fmt);
 							break;
 						case F_U:
 							conv_u(pr, bp);
@@ -663,7 +669,7 @@ static void display(priv_dumper_t* dumper)
 				printf(pr->fmt, (unsigned) dumper->eaddress);
 				break;
 			case F_TEXT:
-				printf(pr->fmt);
+				printf("%s", pr->fmt);
 				break;
 			}
 		}
diff --git i/libbb/fflush_stdout_and_exit.c w/libbb/fflush_stdout_and_exit.c
index 9ad5dbf9..41a14d3d 100644
--- i/libbb/fflush_stdout_and_exit.c
+++ w/libbb/fflush_stdout_and_exit.c
@@ -16,7 +16,7 @@
 void FAST_FUNC fflush_stdout_and_exit(int retval)
 {
 	if (fflush(stdout))
-		bb_perror_msg_and_die(bb_msg_standard_output);
+		bb_perror_msg_and_die("%s", bb_msg_standard_output);
 
 	if (ENABLE_FEATURE_PREFER_APPLETS && die_sleep < 0) {
 		/* We are in NOFORK applet. Do not exit() directly,
diff --git i/libbb/mtab.c w/libbb/mtab.c
index 22bff649..c111203e 100644
--- i/libbb/mtab.c
+++ w/libbb/mtab.c
@@ -22,7 +22,7 @@ void FAST_FUNC erase_mtab(const char *name)
 	/* Bummer. Fall back on trying the /proc filesystem */
 	if (!mountTable) mountTable = setmntent("/proc/mounts", "r");
 	if (!mountTable) {
-		bb_perror_msg(bb_path_mtab_file);
+		bb_perror_msg("%s", bb_path_mtab_file);
 		return;
 	}
 
@@ -50,6 +50,6 @@ void FAST_FUNC erase_mtab(const char *name)
 		}
 		endmntent(mountTable);
 	} else if (errno != EROFS)
-		bb_perror_msg(bb_path_mtab_file);
+		bb_perror_msg("%s", bb_path_mtab_file);
 }
 #endif
diff --git i/libbb/wfopen.c w/libbb/wfopen.c
index 76dc8b82..115b0914 100644
--- i/libbb/wfopen.c
+++ w/libbb/wfopen.c
@@ -43,7 +43,7 @@ static FILE* xfdopen_helper(unsigned fd_and_rw_bit)
 {
 	FILE* fp = fdopen(fd_and_rw_bit >> 1, fd_and_rw_bit & 1 ? "w" : "r");
 	if (!fp)
-		bb_error_msg_and_die(bb_msg_memory_exhausted);
+		bb_error_msg_and_die("%s", bb_msg_memory_exhausted);
 	return fp;
 }
 FILE* FAST_FUNC xfdopen_for_read(int fd)
diff --git i/libbb/xfuncs_printf.c w/libbb/xfuncs_printf.c
index d8a42ba0..b771ba56 100644
--- i/libbb/xfuncs_printf.c
+++ w/libbb/xfuncs_printf.c
@@ -37,7 +37,7 @@ void* FAST_FUNC malloc_or_warn(size_t size)
 {
 	void *ptr = malloc(size);
 	if (ptr == NULL && size != 0)
-		bb_error_msg(bb_msg_memory_exhausted);
+		bb_error_msg("%s", bb_msg_memory_exhausted);
 	return ptr;
 }
 
@@ -46,7 +46,7 @@ void* FAST_FUNC xmalloc(size_t size)
 {
 	void *ptr = malloc(size);
 	if (ptr == NULL && size != 0)
-		bb_error_msg_and_die(bb_msg_memory_exhausted);
+		bb_error_msg_and_die("%s", bb_msg_memory_exhausted);
 	return ptr;
 }
 
@@ -57,7 +57,7 @@ void* FAST_FUNC xrealloc(void *ptr, size_t size)
 {
 	ptr = realloc(ptr, size);
 	if (ptr == NULL && size != 0)
-		bb_error_msg_and_die(bb_msg_memory_exhausted);
+		bb_error_msg_and_die("%s", bb_msg_memory_exhausted);
 	return ptr;
 }
 #endif /* DMALLOC */
@@ -81,7 +81,7 @@ char* FAST_FUNC xstrdup(const char *s)
 	t = strdup(s);
 
 	if (t == NULL)
-		bb_error_msg_and_die(bb_msg_memory_exhausted);
+		bb_error_msg_and_die("%s", bb_msg_memory_exhausted);
 
 	return t;
 }
@@ -299,14 +299,14 @@ char* FAST_FUNC xasprintf(const char *format, ...)
 	va_end(p);
 
 	if (r < 0)
-		bb_error_msg_and_die(bb_msg_memory_exhausted);
+		bb_error_msg_and_die("%s", bb_msg_memory_exhausted);
 	return string_ptr;
 }
 
 void FAST_FUNC xsetenv(const char *key, const char *value)
 {
 	if (setenv(key, value, 1))
-		bb_error_msg_and_die(bb_msg_memory_exhausted);
+		bb_error_msg_and_die("%s", bb_msg_memory_exhausted);
 }
 
 /* Handles "VAR=VAL" strings, even those which are part of environ
diff --git i/loginutils/addgroup.c w/loginutils/addgroup.c
index b37270ff..fd5b40bd 100644
--- i/loginutils/addgroup.c
+++ w/loginutils/addgroup.c
@@ -129,7 +129,7 @@ int addgroup_main(int argc UNUSED_PARAM, char **argv)
 
 	/* need to be root */
 	if (geteuid()) {
-		bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
+		bb_error_msg_and_die("%s", bb_msg_perm_denied_are_you_root);
 	}
 #if ENABLE_FEATURE_ADDGROUP_LONG_OPTIONS
 	applet_long_options = addgroup_longopts;
diff --git i/loginutils/adduser.c w/loginutils/adduser.c
index 1d082c87..2a661007 100644
--- i/loginutils/adduser.c
+++ w/loginutils/adduser.c
@@ -154,7 +154,7 @@ int adduser_main(int argc UNUSED_PARAM, char **argv)
 
 	/* got root? */
 	if (geteuid()) {
-		bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
+		bb_error_msg_and_die("%s", bb_msg_perm_denied_are_you_root);
 	}
 
 	pw.pw_gecos = (char *)"Linux User,,,";
diff --git i/loginutils/chpasswd.c w/loginutils/chpasswd.c
index 54ed7379..9eab99e4 100644
--- i/loginutils/chpasswd.c
+++ w/loginutils/chpasswd.c
@@ -39,7 +39,7 @@ int chpasswd_main(int argc UNUSED_PARAM, char **argv)
 	int opt;
 
 	if (getuid() != 0)
-		bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
+		bb_error_msg_and_die("%s", bb_msg_perm_denied_are_you_root);
 
 	opt_complementary = "m--e:e--m";
 	IF_LONG_OPTS(applet_long_options = chpasswd_longopts;)
diff --git i/loginutils/deluser.c w/loginutils/deluser.c
index e39ac550..ee60efcb 100644
--- i/loginutils/deluser.c
+++ w/loginutils/deluser.c
@@ -38,7 +38,7 @@ int deluser_main(int argc, char **argv)
 	int do_deluser = (ENABLE_DELUSER && (!ENABLE_DELGROUP || applet_name[3] == 'u'));
 
 	if (geteuid() != 0)
-		bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
+		bb_error_msg_and_die("%s", bb_msg_perm_denied_are_you_root);
 
 	name = argv[1];
 	member = NULL;
diff --git i/loginutils/getty.c w/loginutils/getty.c
index bbb5a96b..d2da4e35 100644
--- i/loginutils/getty.c
+++ w/loginutils/getty.c
@@ -463,7 +463,7 @@ static char *get_logname(void)
 				finalize_tty_attrs();
 				if (errno == EINTR || errno == EIO)
 					exit(EXIT_SUCCESS);
-				bb_perror_msg_and_die(bb_msg_read_error);
+				bb_perror_msg_and_die("%s", bb_msg_read_error);
 			}
 
 			switch (c) {
diff --git i/miscutils/crontab.c w/miscutils/crontab.c
index 4731d8da..49d1da7c 100644
--- i/miscutils/crontab.c
+++ w/miscutils/crontab.c
@@ -115,7 +115,7 @@ int crontab_main(int argc UNUSED_PARAM, char **argv)
 	if (sanitize_env_if_suid()) { /* Clears dangerous stuff, sets PATH */
 		/* Run by non-root */
 		if (opt_ler & (OPT_u|OPT_c))
-			bb_error_msg_and_die(bb_msg_you_must_be_root);
+			bb_error_msg_and_die("%s", bb_msg_you_must_be_root);
 	}
 
 	if (opt_ler & OPT_u) {
diff --git i/miscutils/rx.c w/miscutils/rx.c
index af597320..cc39fa2f 100644
--- i/miscutils/rx.c
+++ w/miscutils/rx.c
@@ -110,7 +110,7 @@ static int receive(/*int read_fd, */int file_fd)
 		/* Write previously received block */
 		errno = 0;
 		if (full_write(file_fd, blockBuf, blockLength) != blockLength) {
-			bb_perror_msg(bb_msg_write_error);
+			bb_perror_msg("%s", bb_msg_write_error);
 			goto fatal;
 		}
 
diff --git i/networking/ntpd.c w/networking/ntpd.c
index 603801ec..3b4da4b8 100644
--- i/networking/ntpd.c
+++ w/networking/ntpd.c
@@ -1970,7 +1970,7 @@ static NOINLINE void ntp_init(char **argv)
 	srandom(getpid());
 
 	if (getuid())
-		bb_error_msg_and_die(bb_msg_you_must_be_root);
+		bb_error_msg_and_die("%s", bb_msg_you_must_be_root);
 
 	/* Set some globals */
 	G.stratum = MAXSTRAT;
diff --git i/networking/ntpd_simple.c w/networking/ntpd_simple.c
index 4ad44e4f..9dd2798c 100644
--- i/networking/ntpd_simple.c
+++ w/networking/ntpd_simple.c
@@ -830,7 +830,7 @@ static NOINLINE void ntp_init(char **argv)
 	srandom(getpid());
 
 	if (getuid())
-		bb_error_msg_and_die(bb_msg_you_must_be_root);
+		bb_error_msg_and_die("%s", bb_msg_you_must_be_root);
 
 	peers = NULL;
 	opt_complementary = "dd:p::"; /* d: counter, p: list */
diff --git i/networking/ping.c w/networking/ping.c
index b8a438ba..d7b6fc6a 100644
--- i/networking/ping.c
+++ w/networking/ping.c
@@ -421,7 +421,7 @@ static void sendping_tail(void (*sp)(int), int size_pkt)
 	 * it doesn't matter */
 	sz = xsendto(pingsock, G.snd_packet, size_pkt, &pingaddr.sa, sizeof(pingaddr));
 	if (sz != size_pkt)
-		bb_error_msg_and_die(bb_msg_write_error);
+		bb_error_msg_and_die("%s", bb_msg_write_error);
 
 	if (pingcount == 0 || deadline || ntransmitted < pingcount) {
 		/* Didn't send all pings yet - schedule next in 1s */
diff --git i/networking/tcpudp.c w/networking/tcpudp.c
index 3df6a98d..b80ad3a0 100644
--- i/networking/tcpudp.c
+++ w/networking/tcpudp.c
@@ -278,7 +278,7 @@ int tcpudpsvd_main(int argc UNUSED_PARAM, char **argv)
 	client = 0;
 	if ((getuid() == 0) && !(opts & OPT_u)) {
 		xfunc_exitcode = 100;
-		bb_error_msg_and_die(bb_msg_you_must_be_root);
+		bb_error_msg_and_die("%s", bb_msg_you_must_be_root);
 	}
 	if (opts & OPT_u)
 		if (!uidgid_get(&sslugid, ssluser, 1)) {
diff --git i/networking/traceroute.c w/networking/traceroute.c
index d197e541..dc01ea7c 100644
--- i/networking/traceroute.c
+++ w/networking/traceroute.c
@@ -850,7 +850,7 @@ common_traceroute_main(int op, char **argv)
 		 * probe (e.g., on a multi-homed host).
 		 */
 		if (getuid() != 0)
-			bb_error_msg_and_die(bb_msg_you_must_be_root);
+			bb_error_msg_and_die("%s", bb_msg_you_must_be_root);
 	}
 	if (op & OPT_WAITTIME)
 		waittime = xatou_range(waittime_str, 1, 24 * 60 * 60);
diff --git i/networking/udhcp/arpping.c w/networking/udhcp/arpping.c
index b43e52e9..155ec01e 100644
--- i/networking/udhcp/arpping.c
+++ w/networking/udhcp/arpping.c
@@ -50,7 +50,7 @@ int FAST_FUNC arpping(uint32_t test_nip,
 
 	s = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP));
 	if (s == -1) {
-		bb_perror_msg(bb_msg_can_not_create_raw_socket);
+		bb_perror_msg("%s", bb_msg_can_not_create_raw_socket);
 		return -1;
 	}
 
diff --git i/networking/wget.c w/networking/wget.c
index 1991a107..91eea8c9 100644
--- i/networking/wget.c
+++ w/networking/wget.c
@@ -199,7 +199,7 @@ static FILE *open_socket(len_and_sockaddr *lsa)
 	/* hopefully it understands what ESPIPE means... */
 	fp = fdopen(xconnect_stream(lsa), "r+");
 	if (fp == NULL)
-		bb_perror_msg_and_die(bb_msg_memory_exhausted);
+		bb_perror_msg_and_die("%s", bb_msg_memory_exhausted);
 
 	return fp;
 }
@@ -509,7 +509,7 @@ static void NOINLINE retrieve_file_data(FILE *dfp)
 					continue; /* yes */
 #endif
 				if (ferror(dfp))
-					bb_perror_msg_and_die(bb_msg_read_error);
+					bb_perror_msg_and_die("%s", bb_msg_read_error);
 				break; /* EOF, not error */
 			}
 
diff --git i/networking/zcip.c w/networking/zcip.c
index 7314ff8d..c36a3216 100644
--- i/networking/zcip.c
+++ w/networking/zcip.c
@@ -473,7 +473,7 @@ int zcip_main(int argc UNUSED_PARAM, char **argv)
 
 			// read ARP packet
 			if (safe_read(sock_fd, &p, sizeof(p)) < 0) {
-				bb_perror_msg_and_die(bb_msg_read_error);
+				bb_perror_msg_and_die("%s", bb_msg_read_error);
 			}
 			if (p.eth.ether_type != htons(ETHERTYPE_ARP))
 				continue;
diff --git i/shell/ash.c w/shell/ash.c
index d197fa19..4a6bd0e1 100644
--- i/shell/ash.c
+++ w/shell/ash.c
@@ -3926,7 +3926,7 @@ sprint_status(char *s, int status, int sigonly)
 		}
 		st &= 0x7f;
 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
-		col = fmtstr(s, 32, strsignal(st));
+		col = fmtstr(s, 32, "%s", strsignal(st));
 		if (WCOREDUMP(status)) {
 			col += fmtstr(s + col, 16, " (core dumped)");
 		}
diff --git i/shell/hush.c w/shell/hush.c
index b9e763cc..ddd27d88 100644
--- i/shell/hush.c
+++ w/shell/hush.c
@@ -2548,7 +2548,7 @@ static int glob_brace(char *pattern, o_string *o, int n)
 				return o_save_ptr_helper(o, n);
 			}
 			if (gr == GLOB_NOSPACE)
-				bb_error_msg_and_die(bb_msg_memory_exhausted);
+				bb_error_msg_and_die("%s", bb_msg_memory_exhausted);
 			/* GLOB_ABORTED? Only happens with GLOB_ERR flag,
 			 * but we didn't specify it. Paranoia again. */
 			bb_error_msg_and_die("glob error %d on '%s'", gr, pattern);
@@ -2650,7 +2650,7 @@ static int perform_glob(o_string *o, int n)
 			goto literal;
 		}
 		if (gr == GLOB_NOSPACE)
-			bb_error_msg_and_die(bb_msg_memory_exhausted);
+			bb_error_msg_and_die("%s", bb_msg_memory_exhausted);
 		/* GLOB_ABORTED? Only happens with GLOB_ERR flag,
 		 * but we didn't specify it. Paranoia again. */
 		bb_error_msg_and_die("glob error %d on '%s'", gr, pattern);
diff --git i/sysklogd/logread.c w/sysklogd/logread.c
index 99395690..6eef0330 100644
--- i/sysklogd/logread.c
+++ w/sysklogd/logread.c
@@ -54,7 +54,7 @@ static void error_exit(const char *str)
 {
 	//release all acquired resources
 	shmdt(shbuf);
-	bb_perror_msg_and_die(str);
+	bb_perror_msg_and_die("%s", str);
 }
 
 /*
diff --git i/util-linux/fdformat.c w/util-linux/fdformat.c
index 2f0854a3..c43db5e3 100644
--- i/util-linux/fdformat.c
+++ w/util-linux/fdformat.c
@@ -107,7 +107,7 @@ int fdformat_main(int argc UNUSED_PARAM, char **argv)
 			read_bytes = safe_read(fd, data, n);
 			if (read_bytes != n) {
 				if (read_bytes < 0) {
-					bb_perror_msg(bb_msg_read_error);
+					bb_perror_msg("%s", bb_msg_read_error);
 				}
 				bb_error_msg_and_die("problem reading cylinder %d, "
 					"expected %d, read %d", cyl, n, read_bytes);
diff --git i/util-linux/mount.c w/util-linux/mount.c
index f1da30fa..b465548a 100644
--- i/util-linux/mount.c
+++ w/util-linux/mount.c
@@ -355,7 +355,7 @@ static void FAST_FUNC update_mtab_entry_on_move(const struct mntent *mp)
 
 	mountTable = setmntent(bb_path_mtab_file, "r");
 	if (!mountTable) {
-		bb_perror_msg(bb_path_mtab_file);
+		bb_perror_msg("%s", bb_path_mtab_file);
 		return;
 	}
 
@@ -383,7 +383,7 @@ static void FAST_FUNC update_mtab_entry_on_move(const struct mntent *mp)
 		}
 		endmntent(mountTable);
 	} else if (errno != EROFS)
-		bb_perror_msg(bb_path_mtab_file);
+		bb_perror_msg("%s", bb_path_mtab_file);
 
 	if (ENABLE_FEATURE_CLEAN_UP) {
 		for (i = 0; i < count; i++) {
@@ -602,7 +602,7 @@ static int mount_it_now(struct mntent *mp, long vfsflags, char *filteropts)
 	// Abort entirely if permission denied.
 
 	if (rc && errno == EPERM)
-		bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
+		bb_error_msg_and_die("%s", bb_msg_perm_denied_are_you_root);
 
 	// If the mount was successful, and we're maintaining an old-style
 	// mtab file by hand, add the new entry to it now.
@@ -614,7 +614,7 @@ static int mount_it_now(struct mntent *mp, long vfsflags, char *filteropts)
 		int i;
 
 		if (!mountTable) {
-			bb_perror_msg(bb_path_mtab_file);
+			bb_perror_msg("%s", bb_path_mtab_file);
 			goto ret;
 		}
 
@@ -1856,7 +1856,7 @@ static int singlemount(struct mntent *mp, int ignore_busy)
 			mp->mnt_fsname = NULL; // will receive malloced loop dev name
 			if (set_loop(&mp->mnt_fsname, loopFile, 0, /*ro:*/ 0) < 0) {
 				if (errno == EPERM || errno == EACCES)
-					bb_error_msg(bb_msg_perm_denied_are_you_root);
+					bb_error_msg("%s", bb_msg_perm_denied_are_you_root);
 				else
 					bb_perror_msg("can't setup loop device");
 				return errno;
@@ -2051,7 +2051,7 @@ int mount_main(int argc UNUSED_PARAM, char **argv)
 		// argument when we get it.
 		if (argv[1]) {
 			if (nonroot)
-				bb_error_msg_and_die(bb_msg_you_must_be_root);
+				bb_error_msg_and_die("%s", bb_msg_you_must_be_root);
 			mtpair->mnt_fsname = argv[0];
 			mtpair->mnt_dir = argv[1];
 			mtpair->mnt_type = fstype;
@@ -2068,7 +2068,7 @@ int mount_main(int argc UNUSED_PARAM, char **argv)
 
 	i = parse_mount_options(cmdopts, NULL); // FIXME: should be "long", not "int"
 	if (nonroot && (i & ~MS_SILENT)) // Non-root users cannot specify flags
-		bb_error_msg_and_die(bb_msg_you_must_be_root);
+		bb_error_msg_and_die("%s", bb_msg_you_must_be_root);
 
 	// If we have a shared subtree flag, don't worry about fstab or mtab.
 	if (ENABLE_FEATURE_MOUNT_FLAGS
@@ -2131,7 +2131,7 @@ int mount_main(int argc UNUSED_PARAM, char **argv)
 			// No, mount -a won't mount anything,
 			// even user mounts, for mere humans
 			if (nonroot)
-				bb_error_msg_and_die(bb_msg_you_must_be_root);
+				bb_error_msg_and_die("%s", bb_msg_you_must_be_root);
 
 			// Does type match? (NULL matches always)
 			if (!match_fstype(mtcur, fstype))
@@ -2211,7 +2211,7 @@ int mount_main(int argc UNUSED_PARAM, char **argv)
 			// fstab must have "users" or "user"
 			l = parse_mount_options(mtcur->mnt_opts, NULL);
 			if (!(l & MOUNT_USERS))
-				bb_error_msg_and_die(bb_msg_you_must_be_root);
+				bb_error_msg_and_die("%s", bb_msg_you_must_be_root);
 		}
 
 		//util-linux-2.12 does not do this check.



Reply to: