Skip to contentSkip to conversation

Fix --reuse-cmdline so it is usable.

PATCH In review Eric W. Biederman 3 participants 11 messages Jan 19, 2010 – Feb 2, 2010

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Fix --reuse-cmdline so it is usable.

A colleague of mine implemented kdump and it used --reuse-cmdline with some rather interesting and unexpected results.

Update the getopt specification so that --reuse-cmdline does not attempt to take an argument that it will not use.

Update the processing of --append so that --reuse-cmdline followed by --append actually appends the parameters specified by --reuse-cmdline.

---
 kexec/arch/i386/kexec-bzImage.c       |    8 ++++----
 kexec/arch/i386/kexec-elf-x86.c       |    8 ++++----
 kexec/arch/i386/kexec-multiboot-x86.c |    7 ++++---
 kexec/arch/x86_64/kexec-elf-x86_64.c  |    8 ++++----
 kexec/kexec.c                         |   16 ++++++++++++++++
 kexec/kexec.h                         |    2 ++
 6 files changed, 34 insertions(+), 15 deletions(-)
kexec/arch/i386/kexec-bzImage.c +4 -4
index be88a3f..21c1ddf 100644
@@ -332,7 +332,7 @@ int do_bzImage_load(struct kexec_info *info,
 int bzImage_load(int argc, char **argv, const char *buf, off_t len, 
 	struct kexec_info *info)
 {
-	const char *command_line;
+	const char *command_line = NULL, *append = NULL;
 	const char *ramdisk;
 	char *ramdisk_buf;
 	off_t ramdisk_length;
@@ -349,7 +349,7 @@ int bzImage_load(int argc, char **argv, const char *buf, off_t len,
 		{ "debug",		0, 0, OPT_DEBUG },
 		{ "command-line",	1, 0, OPT_APPEND },
 		{ "append",		1, 0, OPT_APPEND },
-		{ "reuse-cmdline",	1, 0, OPT_REUSE_CMDLINE },
+		{ "reuse-cmdline",	0, 0, OPT_REUSE_CMDLINE },
 		{ "initrd",		1, 0, OPT_RAMDISK },
 		{ "ramdisk",		1, 0, OPT_RAMDISK },
 		{ "real-mode",		0, 0, OPT_REAL_MODE },
@@ -362,7 +362,6 @@ int bzImage_load(int argc, char **argv, const char *buf, off_t len,
 	 */
 	debug = 0;
 	real_mode_entry = 0;
-	command_line = 0;
 	ramdisk = 0;
 	ramdisk_length = 0;
 	while((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) {
@@ -379,7 +378,7 @@ int bzImage_load(int argc, char **argv, const char *buf, off_t len,
 			debug = 1;
 			break;
 		case OPT_APPEND:
-			command_line = optarg;
+			append = optarg;
 			break;
 		case OPT_REUSE_CMDLINE:
 			command_line = get_command_line();
@@ -392,6 +391,7 @@ int bzImage_load(int argc, char **argv, const char *buf, off_t len,
 			break;
 		}
 	}
+	command_line = concat_cmdline(command_line, append);
 	command_line_len = 0;
 	if (command_line) {
 		command_line_len = strlen(command_line) +1;
kexec/arch/i386/kexec-elf-x86.c +4 -4
index afa0eb5..aaf46ba 100644
@@ -88,7 +88,7 @@ int elf_x86_load(int argc, char **argv, const char *buf, off_t len,
 	struct kexec_info *info)
 {
 	struct mem_ehdr ehdr;
-	const char *command_line;
+	const char *command_line = NULL, *append = NULL;
 	char *modified_cmdline;
 	int command_line_len;
 	int modified_cmdline_len;
@@ -110,7 +110,7 @@ int elf_x86_load(int argc, char **argv, const char *buf, off_t len,
 		KEXEC_ARCH_OPTIONS
 		{ "command-line",	1, NULL, OPT_APPEND },
 		{ "append",		1, NULL, OPT_APPEND },
-		{ "reuse-cmdline",	1, NULL, OPT_REUSE_CMDLINE },
+		{ "reuse-cmdline",	0, NULL, OPT_REUSE_CMDLINE },
 		{ "initrd",		1, NULL, OPT_RAMDISK },
 		{ "ramdisk",		1, NULL, OPT_RAMDISK },
 		{ "args-elf",		0, NULL, OPT_ARGS_ELF },
@@ -125,7 +125,6 @@ int elf_x86_load(int argc, char **argv, const char *buf, off_t len,
 	 * Parse the command line arguments
 	 */
 	arg_style = ARG_STYLE_ELF;
-	command_line = 0;
 	modified_cmdline = 0;
 	modified_cmdline_len = 0;
 	ramdisk = 0;
@@ -140,7 +139,7 @@ int elf_x86_load(int argc, char **argv, const char *buf, off_t len,
 			usage();
 			return -1;
 		case OPT_APPEND:
-			command_line = optarg;
+			append = optarg;
 			break;
 		case OPT_REUSE_CMDLINE:
 			command_line = get_command_line();
@@ -163,6 +162,7 @@ int elf_x86_load(int argc, char **argv, const char *buf, off_t len,
 			break;
 		}
 	}
+	command_line = concat_cmdline(command_line, append);
 	command_line_len = 0;
 	if (command_line) {
 		command_line_len = strlen(command_line) +1;
kexec/arch/i386/kexec-multiboot-x86.c +4 -3
index 9b41698..9817ba9 100644
@@ -147,7 +147,7 @@ int multiboot_x86_load(int argc, char **argv, const char *buf, off_t len,
 	unsigned long mbi_base;
 	struct entry32_regs regs;
 	size_t mbi_bytes, mbi_offset;
-	const char *command_line=NULL;
+	const char *command_line=NULL, *append=NULL;
 	char *imagename, *cp;
 	struct memory_range *range;
 	int ranges;
@@ -164,7 +164,7 @@ int multiboot_x86_load(int argc, char **argv, const char *buf, off_t len,
 		KEXEC_ARCH_OPTIONS
 		{ "command-line",		1, 0, OPT_CL },
 		{ "append",			1, 0, OPT_CL },
-		{ "reuse-cmdline",		1, 0, OPT_REUSE_CMDLINE },
+		{ "reuse-cmdline",		0, 0, OPT_REUSE_CMDLINE },
 		{ "module",			1, 0, OPT_MOD },
 		{ 0, 				0, 0, 0 },
 	};
@@ -195,7 +195,7 @@ int multiboot_x86_load(int argc, char **argv, const char *buf, off_t len,
 			usage();
 			return -1;
 		case OPT_CL:
-			command_line = optarg;
+			append = optarg;
 			break;
 		case OPT_REUSE_CMDLINE:
 			command_line = get_command_line();
@@ -207,6 +207,7 @@ int multiboot_x86_load(int argc, char **argv, const char *buf, off_t len,
 		}
 	}
 	imagename = argv[optind];
+	command_line = concat_cmdline(command_line, append);
 	command_line_len = strlen(command_line) + strlen(imagename) + 2;
 
 
kexec/arch/x86_64/kexec-elf-x86_64.c +4 -4
index 95ebef6..901262f 100644
@@ -87,7 +87,7 @@ int elf_x86_64_load(int argc, char **argv, const char *buf, off_t len,
 	struct kexec_info *info)
 {
 	struct mem_ehdr ehdr;
-	const char *command_line;
+	const char *command_line = NULL, *append = NULL;
 	char *modified_cmdline;
 	int command_line_len;
 	int modified_cmdline_len;
@@ -109,7 +109,7 @@ int elf_x86_64_load(int argc, char **argv, const char *buf, off_t len,
 		KEXEC_ARCH_OPTIONS
 		{ "command-line",	1, NULL, OPT_APPEND },
 		{ "append",		1, NULL, OPT_APPEND },
-		{ "reuse-cmdline",	1, NULL, OPT_REUSE_CMDLINE },
+		{ "reuse-cmdline",	0, NULL, OPT_REUSE_CMDLINE },
 		{ "initrd",		1, NULL, OPT_RAMDISK },
 		{ "ramdisk",		1, NULL, OPT_RAMDISK },
 		{ "args-elf",		0, NULL, OPT_ARGS_ELF },
@@ -124,7 +124,6 @@ int elf_x86_64_load(int argc, char **argv, const char *buf, off_t len,
 	 * Parse the command line arguments
 	 */
 	arg_style = ARG_STYLE_ELF;
-	command_line = 0;
 	modified_cmdline = 0;
 	modified_cmdline_len = 0;
 	ramdisk = 0;
@@ -140,7 +139,7 @@ int elf_x86_64_load(int argc, char **argv, const char *buf, off_t len,
 			usage();
 			return -1;
 		case OPT_APPEND:
-			command_line = optarg;
+			append = optarg;
 			break;
 		case OPT_REUSE_CMDLINE:
 			command_line = get_command_line();
@@ -163,6 +162,7 @@ int elf_x86_64_load(int argc, char **argv, const char *buf, off_t len,
 			break;
 		}
 	}
+	command_line = concat_cmdline(command_line, append);
 	command_line_len = 0;
 	if (command_line) {
 		command_line_len = strlen(command_line) +1;
kexec/kexec.c +16 -0
index a1cec86..f4c22a6 100644
@@ -994,6 +994,22 @@ void check_reuse_initrd(void)
 	free(line);
 }
 
+const char *concat_cmdline(const char *base, const char *append)
+{
+	const char *cmdline;
+	if (!base && !append)
+		return NULL;
+	if (!base)
+		return append;
+	if (!append)
+		return base;
+	cmdline = xmalloc(strlen(base) + 1 + strlen(append) + 1);
+	strcpy(cmdline, base);
+	strcat(cmdline, " ");
+	strcat(cmdline, append);
+	return cmdline;
+}
+
 
 int main(int argc, char *argv[])
 {
kexec/kexec.h +2 -0
index 53aa58c..ebc5a95 100644
@@ -261,4 +261,6 @@ static inline int __attribute__ ((format (printf, 1, 2)))
 	dbgprintf(const char *fmt, ...) {return 0;}
 #endif
 
+const char *concat_cmdline(const char *base, const char *append);
+
 #endif /* KEXEC_H */
Signature · 7 lines
1.6.2.5


_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
#1 lore raw
Quoted 9 lines · Eric W. Biederman

A colleague of mine implemented kdump and it used --reuse-cmdline with some rather interesting and unexpected results.

Update the getopt specification so that --reuse-cmdline does not attempt to take an argument that it will not use.

Update the processing of --append so that --reuse-cmdline followed by --append actually appends the parameters specified by --reuse-cmdline.

Hi Eric,

sorry for being slow. Been semi-offline for LCA and am now catching up on things.

[snip]

Quoted 14 lines
kexec/kexec.c +6 -0
index a1cec86..f4c22a6 100644
@@ -994,6 +994,22 @@ void check_reuse_initrd(void)
 	free(line);
 }
 
+const char *concat_cmdline(const char *base, const char *append)
+{
+	const char *cmdline;
+	if (!base && !append)
+		return NULL;
+	if (!base)

kexec/kexec.c void check_reuse_initrd(void) · line 1012

Quoted 10 lines
kexec/kexec.c +10 -0
+		return append;
+	if (!append)
+		return base;
+	cmdline = xmalloc(strlen(base) + 1 + strlen(append) + 1);
+	strcpy(cmdline, base);
+	strcat(cmdline, " ");
+	strcat(cmdline, append);
+	return cmdline;
+}
+

This introduces a memory leak.

Perhaps it should strdup append and base in the !base and !append cases respectively and expect the caller to always call free.

I realise that its a small leak in a programme that will soon exit anyway. But for the sake of being able to use tools like valgrind to analyse problems it seems to me that leaks are worth avoiding. (Not that I have run valgrind on kexec-tools to see what happens :-)

[snip]

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#2 lore raw
Quoted 8 lines · Simon Horman
Quoted 7 lines · Eric W. Biederman

A colleague of mine implemented kdump and it used --reuse-cmdline with some rather interesting and unexpected results.

Update the getopt specification so that --reuse-cmdline does not attempt to take an argument that it will not use.

Quoted 7 lines
Quoted 2 lines

Update the processing of --append so that --reuse-cmdline followed by --append actually appends the parameters specified by --reuse-cmdline.

Hi Eric,

sorry for being slow. Been semi-offline for LCA and am now catching up on things.

No problem, I am pretty out of it right now as well.

Quoted 20 lines

[snip]

Quoted 18 lines
kexec/kexec.c +10 -0
index a1cec86..f4c22a6 100644
@@ -994,6 +994,22 @@ void check_reuse_initrd(void)
 	free(line);
 }
 
+const char *concat_cmdline(const char *base, const char *append)
+{
+	const char *cmdline;
+	if (!base && !append)
+		return NULL;
+	if (!base)
+		return append;
+	if (!append)
+		return base;
+	cmdline = xmalloc(strlen(base) + 1 + strlen(append) + 1);
Quoted 8 lines

kexec/kexec.c void check_reuse_initrd(void) · line 1012

Quoted 6 lines
kexec/kexec.c +6 -0
+	strcpy(cmdline, base);
+	strcat(cmdline, " ");
+	strcat(cmdline, append);
+	return cmdline;
+}
+

This introduces a memory leak.

Yep.

Quoted 7 lines

Perhaps it should strdup append and base in the !base and !append cases respectively and expect the caller to always call free.

I realise that its a small leak in a programme that will soon exit anyway. But for the sake of being able to use tools like valgrind to analyse problems it seems to me that leaks are worth avoiding. (Not that I have run valgrind on kexec-tools to see what happens :-)

I see your point but I think we already have a memory leak here ( Where does the memory that getopt uses come from? ), and I think on a trivial application like /sbin/kexec that is simply not long running it can't matter. I'm even willing to call not freeing memory explicitly a performance optimization in cases like this ;)

Eric

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#4 lore raw
In reply to Eric W. Biederman
Quoted 59 lines · Eric W. Biederman
Quoted 8 lines · Simon Horman
Quoted 7 lines · Eric W. Biederman

A colleague of mine implemented kdump and it used --reuse-cmdline with some rather interesting and unexpected results.

Update the getopt specification so that --reuse-cmdline does not attempt to take an argument that it will not use.

Quoted 7 lines
Quoted 2 lines

Update the processing of --append so that --reuse-cmdline followed by --append actually appends the parameters specified by --reuse-cmdline.

Hi Eric,

sorry for being slow. Been semi-offline for LCA and am now catching up on things.

No problem, I am pretty out of it right now as well.

Quoted 20 lines

[snip]

Quoted 18 lines
kexec/kexec.c +10 -0
index a1cec86..f4c22a6 100644
@@ -994,6 +994,22 @@ void check_reuse_initrd(void)
 	free(line);
 }
 
+const char *concat_cmdline(const char *base, const char *append)
+{
+	const char *cmdline;
+	if (!base && !append)
+		return NULL;
+	if (!base)
+		return append;
+	if (!append)
+		return base;
+	cmdline = xmalloc(strlen(base) + 1 + strlen(append) + 1);
Quoted 8 lines

kexec/kexec.c void check_reuse_initrd(void) · line 1012

Quoted 6 lines
kexec/kexec.c +6 -0
+	strcpy(cmdline, base);
+	strcat(cmdline, " ");
+	strcat(cmdline, append);
+	return cmdline;
+}
+

This introduces a memory leak.

Yep.

Quoted 7 lines

Perhaps it should strdup append and base in the !base and !append cases respectively and expect the caller to always call free.

I realise that its a small leak in a programme that will soon exit anyway. But for the sake of being able to use tools like valgrind to analyse problems it seems to me that leaks are worth avoiding. (Not that I have run valgrind on kexec-tools to see what happens :-)

Quoted 5 lines

I see your point but I think we already have a memory leak here ( Where does the memory that getopt uses come from? ), and I think on a trivial application like /sbin/kexec that is simply not long running it can't matter. I'm even willing to call not freeing memory explicitly a performance optimization in cases like this ;)

Clearly this is a matter of taste. And as it happens I fall on the side of the fence that thinks that the leak should be avoided.

I propose applying the following after your patch:

From: Simon Horman <[email protected]>

don't leak in concat_cmdline

kexec/arch/i386/kexec-bzImage.c +4 -2
Index: kexec-tools/kexec/arch/i386/kexec-bzImage.c
===================================================================
@@ -332,8 +332,8 @@ int do_bzImage_load(struct kexec_info *i
 int bzImage_load(int argc, char **argv, const char *buf, off_t len, 
 	struct kexec_info *info)
 {
-	const char *command_line = NULL, *append = NULL;
-	const char *ramdisk;
+	char *command_line = NULL;
+	const char *ramdisk, *append = NULL;
 	char *ramdisk_buf;
 	off_t ramdisk_length;
 	int command_line_len;
@@ -406,5 +406,7 @@ int bzImage_load(int argc, char **argv, 
 		ramdisk_buf, ramdisk_length,
 		real_mode_entry, debug);
 
+	if (command_line)
+		free(command_line);
 	return result;
 }
kexec/arch/i386/kexec-elf-x86.c +10 -2
Index: kexec-tools/kexec/arch/i386/kexec-elf-x86.c
===================================================================
@@ -88,8 +88,8 @@ int elf_x86_load(int argc, char **argv, 
 	struct kexec_info *info)
 {
 	struct mem_ehdr ehdr;
-	const char *command_line = NULL, *append = NULL;
-	char *modified_cmdline;
+	char *command_line = NULL, *modified_cmdline = NULL;
+	const char *append = NULL;
 	int command_line_len;
 	int modified_cmdline_len;
 	const char *ramdisk;
@@ -264,8 +264,11 @@ int elf_x86_load(int argc, char **argv, 
 			if (rc < 0)
 				return -1;
 			/* Use new command line. */
+			if (command_line)
+				free(command_line);
 			command_line = modified_cmdline;
 			command_line_len = strlen(modified_cmdline) + 1;
+			modified_cmdline = NULL;
 		}
 
 		/* Tell the kernel what is going on */
@@ -288,5 +291,10 @@ int elf_x86_load(int argc, char **argv, 
 	else {
 		die("Unknown argument style\n");
 	}
+
+	if (command_line)
+		free(command_line);
+	if (modified_cmdline)
+		free(modified_cmdline);
 	return 0;
 }
kexec/kexec.c +14 -6
Index: kexec-tools/kexec/kexec.c
===================================================================
@@ -62,6 +62,14 @@ void die(char *fmt, ...)
 	exit(1);
 }
 
+char *xstrdup(const char *str)
+{
+	char *new = strdup(str);
+	if (!new)
+		die("Cannot strdup \"%s\": %s\n",
+			str, strerror(errno));
+	return new;
+}
 
 void *xmalloc(size_t size)
 {
@@ -994,15 +1002,15 @@ void check_reuse_initrd(void)
 	free(line);
 }
 
-const char *concat_cmdline(const char *base, const char *append)
+char *concat_cmdline(const char *base, const char *append)
 {
-	const char *cmdline;
+	char *cmdline;
 	if (!base && !append)
 		return NULL;
-	if (!base)
-		return append;
-	if (!append)
-		return base;
+	if (append)
+		return xstrdup(append);
+	if (base)
+		return xstrdup(base);
 	cmdline = xmalloc(strlen(base) + 1 + strlen(append) + 1);
 	strcpy(cmdline, base);
 	strcat(cmdline, " ");
kexec/arch/i386/kexec-multiboot-x86.c +4 -2
Index: kexec-tools/kexec/arch/i386/kexec-multiboot-x86.c
===================================================================
@@ -147,8 +147,8 @@ int multiboot_x86_load(int argc, char **
 	unsigned long mbi_base;
 	struct entry32_regs regs;
 	size_t mbi_bytes, mbi_offset;
-	const char *command_line=NULL, *append=NULL;
-	char *imagename, *cp;
+	char *command_line = NULL;
+	char *imagename, *cp, *append = NULL;;
 	struct memory_range *range;
 	int ranges;
 	struct AddrRangeDesc *mmap;
@@ -389,6 +389,8 @@ int multiboot_x86_load(int argc, char **
 	regs.eip = ehdr.e_entry;
 	elf_rel_set_symbol(&info->rhdr, "entry32_regs", &regs, sizeof(regs));
 
+	if (command_line)
+		free(command_line);
 	return 0;
 }
 
kexec/arch/x86_64/kexec-elf-x86_64.c +10 -2
Index: kexec-tools/kexec/arch/x86_64/kexec-elf-x86_64.c
===================================================================
@@ -87,8 +87,8 @@ int elf_x86_64_load(int argc, char **arg
 	struct kexec_info *info)
 {
 	struct mem_ehdr ehdr;
-	const char *command_line = NULL, *append = NULL;
-	char *modified_cmdline;
+	const char *append = NULL;
+	char *command_line = NULL, *modified_cmdline;
 	int command_line_len;
 	int modified_cmdline_len;
 	const char *ramdisk;
@@ -249,8 +249,11 @@ int elf_x86_64_load(int argc, char **arg
 			if (rc < 0)
 				return -1;
 			/* Use new command line. */
+			if (command_line)
+				free(command_line);
 			command_line = modified_cmdline;
 			command_line_len = strlen(modified_cmdline) + 1;
+			modified_cmdline = NULL;
 		}
 
 		/* Tell the kernel what is going on */
@@ -273,5 +276,10 @@ int elf_x86_64_load(int argc, char **arg
 	else {
 		die("Unknown argument style\n");
 	}
+
+	if (command_line)
+		free(command_line);
+	if (modified_cmdline)
+		free(modified_cmdline);
 	return 0;
 }
kexec/kexec.h +1 -1
Index: kexec-tools/kexec/kexec.h
===================================================================
@@ -261,6 +261,6 @@ static inline int __attribute__ ((format
 	dbgprintf(const char *fmt, ...) {return 0;}
 #endif
 
-const char *concat_cmdline(const char *base, const char *append);
+char *concat_cmdline(const char *base, const char *append);
 
 #endif /* KEXEC_H */

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#5 lore raw
Quoted 66 lines · Simon Horman
Quoted 59 lines · Eric W. Biederman
Quoted 8 lines · Simon Horman
Quoted 7 lines · Eric W. Biederman

A colleague of mine implemented kdump and it used --reuse-cmdline with some rather interesting and unexpected results.

Update the getopt specification so that --reuse-cmdline does not attempt to take an argument that it will not use.

Quoted 7 lines
Quoted 2 lines

Update the processing of --append so that --reuse-cmdline followed by --append actually appends the parameters specified by --reuse-cmdline.

Hi Eric,

sorry for being slow. Been semi-offline for LCA and am now catching up on things.

No problem, I am pretty out of it right now as well.

Quoted 20 lines

[snip]

Quoted 18 lines
kexec/kexec.c +10 -0
index a1cec86..f4c22a6 100644
@@ -994,6 +994,22 @@ void check_reuse_initrd(void)
 	free(line);
 }
 
+const char *concat_cmdline(const char *base, const char *append)
+{
+	const char *cmdline;
+	if (!base && !append)
+		return NULL;
+	if (!base)
+		return append;
+	if (!append)
+		return base;
+	cmdline = xmalloc(strlen(base) + 1 + strlen(append) + 1);
Quoted 8 lines

kexec/kexec.c void check_reuse_initrd(void) · line 1012

Quoted 6 lines
kexec/kexec.c +6 -0
+	strcpy(cmdline, base);
+	strcat(cmdline, " ");
+	strcat(cmdline, append);
+	return cmdline;
+}
+

This introduces a memory leak.

Yep.

Quoted 7 lines

Perhaps it should strdup append and base in the !base and !append cases respectively and expect the caller to always call free.

I realise that its a small leak in a programme that will soon exit anyway. But for the sake of being able to use tools like valgrind to analyse problems it seems to me that leaks are worth avoiding. (Not that I have run valgrind on kexec-tools to see what happens :-)

Quoted 5 lines

I see your point but I think we already have a memory leak here ( Where does the memory that getopt uses come from? ), and I think on a trivial application like /sbin/kexec that is simply not long running it can't matter. I'm even willing to call not freeing memory explicitly a performance optimization in cases like this ;)

Quoted 8 lines

Clearly this is a matter of taste. And as it happens I fall on the side of the fence that thinks that the leak should be avoided.

I propose applying the following after your patch:

From: Simon Horman <[email protected]>

don't leak in concat_cmdline

It is a bit of a shame that we loose the const attributes. Beyond that the idiom
if (xyz)
free(xyz)
can just become:
free(xyz)

Eric

Quoted 171 lines

Index: kexec-tools/kexec/arch/i386/kexec-bzImage.c
===================================================================

kexec/arch/i386/kexec-bzImage.c +4 -2
@@ -332,8 +332,8 @@ int do_bzImage_load(struct kexec_info *i
 int bzImage_load(int argc, char **argv, const char *buf, off_t len, 
 	struct kexec_info *info)
 {
-	const char *command_line = NULL, *append = NULL;
-	const char *ramdisk;
+	char *command_line = NULL;
+	const char *ramdisk, *append = NULL;
 	char *ramdisk_buf;
 	off_t ramdisk_length;
 	int command_line_len;
@@ -406,5 +406,7 @@ int bzImage_load(int argc, char **argv, 
 		ramdisk_buf, ramdisk_length,
 		real_mode_entry, debug);
 
+	if (command_line)
+		free(command_line);
 	return result;
 }

Index: kexec-tools/kexec/arch/i386/kexec-elf-x86.c
===================================================================

kexec/arch/i386/kexec-elf-x86.c +10 -2
@@ -88,8 +88,8 @@ int elf_x86_load(int argc, char **argv, 
 	struct kexec_info *info)
 {
 	struct mem_ehdr ehdr;
-	const char *command_line = NULL, *append = NULL;
-	char *modified_cmdline;
+	char *command_line = NULL, *modified_cmdline = NULL;
+	const char *append = NULL;
 	int command_line_len;
 	int modified_cmdline_len;
 	const char *ramdisk;
@@ -264,8 +264,11 @@ int elf_x86_load(int argc, char **argv, 
 			if (rc < 0)
 				return -1;
 			/* Use new command line. */
+			if (command_line)
+				free(command_line);
 			command_line = modified_cmdline;
 			command_line_len = strlen(modified_cmdline) + 1;
+			modified_cmdline = NULL;
 		}
 
 		/* Tell the kernel what is going on */
@@ -288,5 +291,10 @@ int elf_x86_load(int argc, char **argv, 
 	else {
 		die("Unknown argument style\n");
 	}
+
+	if (command_line)
+		free(command_line);
+	if (modified_cmdline)
+		free(modified_cmdline);
 	return 0;
 }

Index: kexec-tools/kexec/kexec.c
===================================================================

kexec/kexec.c +14 -6
@@ -62,6 +62,14 @@ void die(char *fmt, ...)
 	exit(1);
 }
 
+char *xstrdup(const char *str)
+{
+	char *new = strdup(str);
+	if (!new)
+		die("Cannot strdup \"%s\": %s\n",
+			str, strerror(errno));
+	return new;
+}
 
 void *xmalloc(size_t size)
 {
@@ -994,15 +1002,15 @@ void check_reuse_initrd(void)
 	free(line);
 }
 
-const char *concat_cmdline(const char *base, const char *append)
+char *concat_cmdline(const char *base, const char *append)
 {
-	const char *cmdline;
+	char *cmdline;
 	if (!base && !append)
 		return NULL;
-	if (!base)
-		return append;
-	if (!append)
-		return base;
+	if (append)
+		return xstrdup(append);
+	if (base)
+		return xstrdup(base);
 	cmdline = xmalloc(strlen(base) + 1 + strlen(append) + 1);
 	strcpy(cmdline, base);
 	strcat(cmdline, " ");

Index: kexec-tools/kexec/arch/i386/kexec-multiboot-x86.c
===================================================================

kexec/arch/i386/kexec-multiboot-x86.c +4 -2
@@ -147,8 +147,8 @@ int multiboot_x86_load(int argc, char **
 	unsigned long mbi_base;
 	struct entry32_regs regs;
 	size_t mbi_bytes, mbi_offset;
-	const char *command_line=NULL, *append=NULL;
-	char *imagename, *cp;
+	char *command_line = NULL;
+	char *imagename, *cp, *append = NULL;;
 	struct memory_range *range;
 	int ranges;
 	struct AddrRangeDesc *mmap;
@@ -389,6 +389,8 @@ int multiboot_x86_load(int argc, char **
 	regs.eip = ehdr.e_entry;
 	elf_rel_set_symbol(&info->rhdr, "entry32_regs", &regs, sizeof(regs));
 
+	if (command_line)
+		free(command_line);
 	return 0;
 }
 

Index: kexec-tools/kexec/arch/x86_64/kexec-elf-x86_64.c
===================================================================

kexec/arch/x86_64/kexec-elf-x86_64.c +10 -2
@@ -87,8 +87,8 @@ int elf_x86_64_load(int argc, char **arg
 	struct kexec_info *info)
 {
 	struct mem_ehdr ehdr;
-	const char *command_line = NULL, *append = NULL;
-	char *modified_cmdline;
+	const char *append = NULL;
+	char *command_line = NULL, *modified_cmdline;
 	int command_line_len;
 	int modified_cmdline_len;
 	const char *ramdisk;
@@ -249,8 +249,11 @@ int elf_x86_64_load(int argc, char **arg
 			if (rc < 0)
 				return -1;
 			/* Use new command line. */
+			if (command_line)
+				free(command_line);
 			command_line = modified_cmdline;
 			command_line_len = strlen(modified_cmdline) + 1;
+			modified_cmdline = NULL;
 		}
 
 		/* Tell the kernel what is going on */
@@ -273,5 +276,10 @@ int elf_x86_64_load(int argc, char **arg
 	else {
 		die("Unknown argument style\n");
 	}
+
+	if (command_line)
+		free(command_line);
+	if (modified_cmdline)
+		free(modified_cmdline);
 	return 0;
 }

Index: kexec-tools/kexec/kexec.h
===================================================================

kexec/kexec.h static inline int __attribute__ ((format · line 266

Quoted 7 lines
kexec/kexec.h +1 -1
@@ -261,6 +261,6 @@ static inline int __attribute__ ((format
 	dbgprintf(const char *fmt, ...) {return 0;}
 #endif
 
-const char *concat_cmdline(const char *base, const char *append);
+char *concat_cmdline(const char *base, const char *append);
 
 #endif /* KEXEC_H */

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#6 lore raw
Quoted 71 lines · Eric W. Biederman
Quoted 69 lines · Simon Horman
Quoted 59 lines · Eric W. Biederman
Quoted 8 lines · Simon Horman
Quoted 7 lines · Eric W. Biederman

A colleague of mine implemented kdump and it used --reuse-cmdline with some rather interesting and unexpected results.

Update the getopt specification so that --reuse-cmdline does not attempt to take an argument that it will not use.

Quoted 7 lines
Quoted 2 lines

Update the processing of --append so that --reuse-cmdline followed by --append actually appends the parameters specified by --reuse-cmdline.

Hi Eric,

sorry for being slow. Been semi-offline for LCA and am now catching up on things.

No problem, I am pretty out of it right now as well.

Quoted 20 lines

[snip]

Quoted 18 lines
kexec/kexec.c +10 -0
index a1cec86..f4c22a6 100644
@@ -994,6 +994,22 @@ void check_reuse_initrd(void)
 	free(line);
 }
 
+const char *concat_cmdline(const char *base, const char *append)
+{
+	const char *cmdline;
+	if (!base && !append)
+		return NULL;
+	if (!base)
+		return append;
+	if (!append)
+		return base;
+	cmdline = xmalloc(strlen(base) + 1 + strlen(append) + 1);
Quoted 8 lines

kexec/kexec.c void check_reuse_initrd(void) · line 1012

Quoted 6 lines
kexec/kexec.c +6 -0
+	strcpy(cmdline, base);
+	strcat(cmdline, " ");
+	strcat(cmdline, append);
+	return cmdline;
+}
+

This introduces a memory leak.

Yep.

Quoted 7 lines

Perhaps it should strdup append and base in the !base and !append cases respectively and expect the caller to always call free.

I realise that its a small leak in a programme that will soon exit anyway. But for the sake of being able to use tools like valgrind to analyse problems it seems to me that leaks are worth avoiding. (Not that I have run valgrind on kexec-tools to see what happens :-)

Quoted 5 lines

I see your point but I think we already have a memory leak here ( Where does the memory that getopt uses come from? ), and I think on a trivial application like /sbin/kexec that is simply not long running it can't matter. I'm even willing to call not freeing memory explicitly a performance optimization in cases like this ;)

Clearly this is a matter of taste. And as it happens I fall on the side of the fence that thinks that the leak should be avoided.

Quoted 7 lines
Quoted 5 lines

I propose applying the following after your patch:

From: Simon Horman <[email protected]>

don't leak in concat_cmdline

It is a bit of a shame that we loose the const attributes.

Indeed, though it seems to be at least partially broken in your original patch.

# gcc --version
gcc (Debian 4.4.2-8) 4.4.2
Copyright (C) 2009 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# make
kexec/kexec.c: In function ‘concat_cmdline’:
kexec/kexec.c:1007: warning: passing argument 1 of ‘strcpy’ discards qualifiers from pointer target type
/usr/include/string.h:127: note: expected ‘char * __restrict__’ but argument is of type ‘const char *’
kexec/kexec.c:1008: warning: passing argument 1 of ‘strcat’ discards qualifiers from pointer target type
/usr/include/string.h:135: note: expected ‘char * __restrict__’ but argument is of type ‘const char *’
kexec/kexec.c:1009: warning: passing argument 1 of ‘strcat’ discards qualifiers from pointer target type
/usr/include/string.h:135: note: expected ‘char * __restrict__’ but argument is of type ‘const char *’
Quoted 5 lines

Beyond that the idiom
if (xyz)
free(xyz)
can just become:
free(xyz)

concat_cmdline() may return NULL in the case where both base and append are NULL.

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#7 lore raw
Quoted 88 lines · Simon Horman
Quoted 71 lines · Eric W. Biederman
Quoted 69 lines · Simon Horman
Quoted 59 lines · Eric W. Biederman
Quoted 8 lines · Simon Horman
Quoted 7 lines · Eric W. Biederman

A colleague of mine implemented kdump and it used --reuse-cmdline with some rather interesting and unexpected results.

Update the getopt specification so that --reuse-cmdline does not attempt to take an argument that it will not use.

Quoted 7 lines
Quoted 2 lines

Update the processing of --append so that --reuse-cmdline followed by --append actually appends the parameters specified by --reuse-cmdline.

Hi Eric,

sorry for being slow. Been semi-offline for LCA and am now catching up on things.

No problem, I am pretty out of it right now as well.

Quoted 20 lines

[snip]

Quoted 18 lines
kexec/kexec.c +10 -0
index a1cec86..f4c22a6 100644
@@ -994,6 +994,22 @@ void check_reuse_initrd(void)
 	free(line);
 }
 
+const char *concat_cmdline(const char *base, const char *append)
+{
+	const char *cmdline;
+	if (!base && !append)
+		return NULL;
+	if (!base)
+		return append;
+	if (!append)
+		return base;
+	cmdline = xmalloc(strlen(base) + 1 + strlen(append) + 1);
Quoted 8 lines

kexec/kexec.c void check_reuse_initrd(void) · line 1012

Quoted 6 lines
kexec/kexec.c +6 -0
+	strcpy(cmdline, base);
+	strcat(cmdline, " ");
+	strcat(cmdline, append);
+	return cmdline;
+}
+

This introduces a memory leak.

Yep.

Quoted 7 lines

Perhaps it should strdup append and base in the !base and !append cases respectively and expect the caller to always call free.

I realise that its a small leak in a programme that will soon exit anyway. But for the sake of being able to use tools like valgrind to analyse problems it seems to me that leaks are worth avoiding. (Not that I have run valgrind on kexec-tools to see what happens :-)

Quoted 5 lines

I see your point but I think we already have a memory leak here ( Where does the memory that getopt uses come from? ), and I think on a trivial application like /sbin/kexec that is simply not long running it can't matter. I'm even willing to call not freeing memory explicitly a performance optimization in cases like this ;)

Clearly this is a matter of taste. And as it happens I fall on the side of the fence that thinks that the leak should be avoided.

Quoted 7 lines
Quoted 5 lines

I propose applying the following after your patch:

From: Simon Horman <[email protected]>

don't leak in concat_cmdline

It is a bit of a shame that we loose the const attributes.

Indeed, though it seems to be at least partially broken in your original patch.

# gcc --version
gcc (Debian 4.4.2-8) 4.4.2
Copyright (C) 2009 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Quoted 8 lines
# make
kexec/kexec.c: In function ‘concat_cmdline’:
kexec/kexec.c:1007: warning: passing argument 1 of ‘strcpy’ discards qualifiers from pointer target type
/usr/include/string.h:127: note: expected ‘char * __restrict__’ but argument is of type ‘const char *’
kexec/kexec.c:1008: warning: passing argument 1 of ‘strcat’ discards qualifiers from pointer target type
/usr/include/string.h:135: note: expected ‘char * __restrict__’ but argument is of type ‘const char *’
kexec/kexec.c:1009: warning: passing argument 1 of ‘strcat’ discards qualifiers from pointer target type
/usr/include/string.h:135: note: expected ‘char * __restrict__’ but argument is of type ‘const char *’

Odd. I did not see those errors, but those are definitely bugs in concat_cmdline.

Quoted 8 lines
Quoted 5 lines

Beyond that the idiom
if (xyz)
free(xyz)
can just become:
free(xyz)

concat_cmdline() may return NULL in the case where both base and append are NULL.

free is well defined when passed NULL. At least according to my local manpages.

Eric

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#8 lore raw
Quoted 108 lines · Eric W. Biederman
Quoted 88 lines · Simon Horman
Quoted 71 lines · Eric W. Biederman
Quoted 69 lines · Simon Horman
Quoted 59 lines · Eric W. Biederman
Quoted 8 lines · Simon Horman
Quoted 7 lines · Eric W. Biederman

A colleague of mine implemented kdump and it used --reuse-cmdline with some rather interesting and unexpected results.

Update the getopt specification so that --reuse-cmdline does not attempt to take an argument that it will not use.

Quoted 7 lines
Quoted 2 lines

Update the processing of --append so that --reuse-cmdline followed by --append actually appends the parameters specified by --reuse-cmdline.

Hi Eric,

sorry for being slow. Been semi-offline for LCA and am now catching up on things.

No problem, I am pretty out of it right now as well.

Quoted 20 lines

[snip]

Quoted 18 lines
kexec/kexec.c +10 -0
index a1cec86..f4c22a6 100644
@@ -994,6 +994,22 @@ void check_reuse_initrd(void)
 	free(line);
 }
 
+const char *concat_cmdline(const char *base, const char *append)
+{
+	const char *cmdline;
+	if (!base && !append)
+		return NULL;
+	if (!base)
+		return append;
+	if (!append)
+		return base;
+	cmdline = xmalloc(strlen(base) + 1 + strlen(append) + 1);
Quoted 8 lines

kexec/kexec.c void check_reuse_initrd(void) · line 1012

Quoted 6 lines
kexec/kexec.c +6 -0
+	strcpy(cmdline, base);
+	strcat(cmdline, " ");
+	strcat(cmdline, append);
+	return cmdline;
+}
+

This introduces a memory leak.

Yep.

Quoted 7 lines

Perhaps it should strdup append and base in the !base and !append cases respectively and expect the caller to always call free.

I realise that its a small leak in a programme that will soon exit anyway. But for the sake of being able to use tools like valgrind to analyse problems it seems to me that leaks are worth avoiding. (Not that I have run valgrind on kexec-tools to see what happens :-)

Quoted 5 lines

I see your point but I think we already have a memory leak here ( Where does the memory that getopt uses come from? ), and I think on a trivial application like /sbin/kexec that is simply not long running it can't matter. I'm even willing to call not freeing memory explicitly a performance optimization in cases like this ;)

Clearly this is a matter of taste. And as it happens I fall on the side of the fence that thinks that the leak should be avoided.

Quoted 7 lines
Quoted 5 lines

I propose applying the following after your patch:

From: Simon Horman <[email protected]>

don't leak in concat_cmdline

It is a bit of a shame that we loose the const attributes.

Indeed, though it seems to be at least partially broken in your original patch.

# gcc --version
gcc (Debian 4.4.2-8) 4.4.2
Copyright (C) 2009 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Quoted 8 lines
# make
kexec/kexec.c: In function ‘concat_cmdline’:
kexec/kexec.c:1007: warning: passing argument 1 of ‘strcpy’ discards qualifiers from pointer target type
/usr/include/string.h:127: note: expected ‘char * __restrict__’ but argument is of type ‘const char *’
kexec/kexec.c:1008: warning: passing argument 1 of ‘strcat’ discards qualifiers from pointer target type
/usr/include/string.h:135: note: expected ‘char * __restrict__’ but argument is of type ‘const char *’
kexec/kexec.c:1009: warning: passing argument 1 of ‘strcat’ discards qualifiers from pointer target type
/usr/include/string.h:135: note: expected ‘char * __restrict__’ but argument is of type ‘const char *’

Odd. I did not see those errors, but those are definitely bugs in concat_cmdline.

Quoted 6 lines
Quoted 5 lines

Beyond that the idiom
if (xyz)
free(xyz)
can just become:
free(xyz)

Quoted 5 lines
Quoted 2 lines

concat_cmdline() may return NULL in the case where both base and append are NULL.

free is well defined when passed NULL. At least according to my local manpages.

Noted, I'll make the change you suggested.

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec