Skip to contentSkip to conversation

init - fix building bug and potential buffer overflow

PATCH In review Cyrill Gorcunov 6 participants 14 messages May 14, 2008 – May 16, 2008

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

PATCH 1/1 init - fix building bug and potential buffer overflow

This patch does fix build bug on m68k wich does not have strncat in straight way.

What is more important - my previous patch

commit e662e1cfd434aa234b72fbc781f1d70211cb785b

Author: Cyrill Gorcunov <[email protected]>
Date:   Mon May 12 14:02:22 2008 -0700

init: don't lose initcall return values

has introduced potential buffer overflow by wrong calculation of string accumulator size.

Many thanks Andreas Schwab and Geert Uytterhoeven for helping to catch and fix the bug.

---

init/main.c +3 -3
Index: linux-2.6.git/init/main.c
===================================================================
@@ -702,7 +702,7 @@ static void __init do_initcalls(void)
 
 	for (call = __initcall_start; call < __initcall_end; call++) {
 		ktime_t t0, t1, delta;
-		char msgbuf[40];
+		char msgbuf[64];
 		int result;
 
 		if (initcall_debug) {
@@ -729,11 +729,11 @@ static void __init do_initcalls(void)
 			sprintf(msgbuf, "error code %d ", result);
 
 		if (preempt_count() != count) {
-			strncat(msgbuf, "preemption imbalance ", sizeof(msgbuf));
+			strcat(msgbuf, "preemption imbalance ");
 			preempt_count() = count;
 		}
 		if (irqs_disabled()) {
-			strncat(msgbuf, "disabled interrupts ", sizeof(msgbuf));
+			strcat(msgbuf, "disabled interrupts ");
 			local_irq_enable();
 		}
 		if (msgbuf[0]) {
#1 lore raw
Quoted 36 lines · On Wed, 14 May 2008 19:44:02 +0400 Cyrill Gorcunov <[email protected]> wrote:

This patch does fix build bug on m68k wich does not have strncat in straight way.

What is more important - my previous patch

commit e662e1cfd434aa234b72fbc781f1d70211cb785b

Author: Cyrill Gorcunov <[email protected]>
Date:   Mon May 12 14:02:22 2008 -0700

init: don't lose initcall return values

has introduced potential buffer overflow by wrong calculation of string accumulator size.

Many thanks Andreas Schwab and Geert Uytterhoeven for helping to catch and fix the bug.

---

Index: linux-2.6.git/init/main.c
===================================================================

init/main.c +1 -1
@@ -702,7 +702,7 @@ static void __init do_initcalls(void)
 
 	for (call = __initcall_start; call < __initcall_end; call++) {
 		ktime_t t0, t1, delta;
-		char msgbuf[40];
+		char msgbuf[64];
 		int result;
 
 		if (initcall_debug) {
@@ -729,11 +729,11 @@ static void __init do_initcalls(void)
 			sprintf(msgbuf, "error code %d ", result);
 
 		if (preempt_count() != count) {

init/main.c static void __init do_initcalls(void) · line 739

Quoted 10 lines
init/main.c +2 -2
-			strncat(msgbuf, "preemption imbalance ", sizeof(msgbuf));
+			strcat(msgbuf, "preemption imbalance ");
 			preempt_count() = count;
 		}
 		if (irqs_disabled()) {
-			strncat(msgbuf, "disabled interrupts ", sizeof(msgbuf));
+			strcat(msgbuf, "disabled interrupts ");
 			local_irq_enable();
 		}
 		if (msgbuf[0]) {

umm, why can't m68k call strncat() from init/main.c??

#2 lore raw

[Andrew Morton - Thu, May 15, 2008 at 10:58:03AM -0700]

| On Wed, 14 May 2008 19:44:02 +0400 Cyrill Gorcunov <[email protected]> wrote:
| 
| > This patch does fix build bug on m68k wich does not have strncat in straight way.
| > 
| > What is more important - my previous patch
| > 
| > commit e662e1cfd434aa234b72fbc781f1d70211cb785b
| > Author: Cyrill Gorcunov <[email protected]>
| > Date:   Mon May 12 14:02:22 2008 -0700
| > 
| >     init: don't lose initcall return values
| > 
| > has introduced potential buffer overflow by wrong calculation
| > of string accumulator size.
| > 
| > Many thanks Andreas Schwab and Geert Uytterhoeven for helping
| > to catch and fix the bug.
| > 
| > Signed-off-by: Cyrill Gorcunov <[email protected]>
| > ---
| > 
| > Index: linux-2.6.git/init/main.c
| > ===================================================================
| > --- linux-2.6.git.orig/init/main.c	2008-05-14 17:55:10.000000000 +0400
| > +++ linux-2.6.git/init/main.c	2008-05-14 19:11:18.000000000 +0400
| > @@ -702,7 +702,7 @@ static void __init do_initcalls(void)
| >  
| >  	for (call = __initcall_start; call < __initcall_end; call++) {
| >  		ktime_t t0, t1, delta;
| > -		char msgbuf[40];
| > +		char msgbuf[64];
| >  		int result;
| >  
| >  		if (initcall_debug) {
| > @@ -729,11 +729,11 @@ static void __init do_initcalls(void)
| >  			sprintf(msgbuf, "error code %d ", result);
| >  
| >  		if (preempt_count() != count) {
| > -			strncat(msgbuf, "preemption imbalance ", sizeof(msgbuf));
| > +			strcat(msgbuf, "preemption imbalance ");
| >  			preempt_count() = count;
| >  		}
| >  		if (irqs_disabled()) {
| > -			strncat(msgbuf, "disabled interrupts ", sizeof(msgbuf));
| > +			strcat(msgbuf, "disabled interrupts ");
| >  			local_irq_enable();
| >  		}
| >  		if (msgbuf[0]) {
| 
| umm, why can't m68k call strncat() from init/main.c??
| 

there some problem with headers iirc, we have to declare it first or use some gcc option (as Adrian suggested). Actually I would prefer to use strlcat there but it seems it would fail to build too. Originally I've messed strlcat with strncat :(

- Cyrill -

#3 lore raw
Quoted 53 lines · Cyrill Gorcunov

[Andrew Morton - Thu, May 15, 2008 at 10:58:03AM -0700]

| On Wed, 14 May 2008 19:44:02 +0400 Cyrill Gorcunov <[email protected]> wrote:
| 
| > This patch does fix build bug on m68k wich does not have strncat in straight way.
| > 
| > What is more important - my previous patch
| > 
| > commit e662e1cfd434aa234b72fbc781f1d70211cb785b
| > Author: Cyrill Gorcunov <[email protected]>
| > Date:   Mon May 12 14:02:22 2008 -0700
| > 
| >     init: don't lose initcall return values
| > 
| > has introduced potential buffer overflow by wrong calculation
| > of string accumulator size.
| > 
| > Many thanks Andreas Schwab and Geert Uytterhoeven for helping
| > to catch and fix the bug.
| > 
| > Signed-off-by: Cyrill Gorcunov <[email protected]>
| > ---
| > 
| > Index: linux-2.6.git/init/main.c
| > ===================================================================
| > --- linux-2.6.git.orig/init/main.c	2008-05-14 17:55:10.000000000 +0400
| > +++ linux-2.6.git/init/main.c	2008-05-14 19:11:18.000000000 +0400
| > @@ -702,7 +702,7 @@ static void __init do_initcalls(void)
| >  
| >  	for (call = __initcall_start; call < __initcall_end; call++) {
| >  		ktime_t t0, t1, delta;
| > -		char msgbuf[40];
| > +		char msgbuf[64];
| >  		int result;
| >  
| >  		if (initcall_debug) {
| > @@ -729,11 +729,11 @@ static void __init do_initcalls(void)
| >  			sprintf(msgbuf, "error code %d ", result);
| >  
| >  		if (preempt_count() != count) {
| > -			strncat(msgbuf, "preemption imbalance ", sizeof(msgbuf));
| > +			strcat(msgbuf, "preemption imbalance ");
| >  			preempt_count() = count;
| >  		}
| >  		if (irqs_disabled()) {
| > -			strncat(msgbuf, "disabled interrupts ", sizeof(msgbuf));
| > +			strcat(msgbuf, "disabled interrupts ");
| >  			local_irq_enable();
| >  		}
| >  		if (msgbuf[0]) {
| 
| umm, why can't m68k call strncat() from init/main.c??
| 
Quoted 2 lines

there some problem with headers iirc, we have to declare it first or use some gcc option (as Adrian suggested). Actually I would prefer to use

gcc turns the strncat() into an implicit call to strlen() and some form of expanded memcpy(). E.g.

	if (preempt_count() != count) {
		strncat(msgbuf, "preemption imbalance ", sizeof(msgbuf));
		preempt_count() = count;
	}

becomes

        cmp.l 884(%a2),%d6      | <variable>.thread.info.preempt_count, count
        jeq .L61        |
        move.l %d7,-(%sp)       | tmp76,
        jbsr strlen     |
        addq.l #4,%sp   |,
        move.l %d7,%a0  | tmp76, tmp80
        add.l %d0,%a0   |, tmp80
        move.l #1886545253,(%a0)+       |,
        move.l #1836086377,(%a0)+       |,
        move.l #1869488233,(%a0)+       |,
        move.l #1835164012,(%a0)+       |,
        move.l #1634624357,(%a0)+       |,
        move.w #8192,(%a0)      |,* D.28541
        move.l %d6,884(%a2)     | count, <variable>.thread.info.preempt_count

.L61:

All other explicit calls to strlen() are inlined, as per include/asm-m68k/string.h.

Quoted 2 lines

strlcat there but it seems it would fail to build too. Originally I've messed strlcat with strncat :(

Actually it build and runs fine after s/strncat/strlcat/...

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]

In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds

#4 lore raw

Could you please make an update to the patch? I can make it only tomorrow evening (ie not that fast)

Quoted 110 lines · Geert Uytterhoeven
Quoted 55 lines · Cyrill Gorcunov

[Andrew Morton - Thu, May 15, 2008 at 10:58:03AM -0700]
| On Wed, 14 May 2008 19:44:02 +0400 Cyrill Gorcunov <[email protected]> wrote:
|
| > This patch does fix build bug on m68k wich does not have strncat in straight way.

| >
| > What is more important - my previous patch
| >
| > commit e662e1cfd434aa234b72fbc781f1d70211cb785b
| > Author: Cyrill Gorcunov <[email protected]>
| > Date:   Mon May 12 14:02:22 2008 -0700
| >
| >     init: don't lose initcall return values
| >
| > has introduced potential buffer overflow by wrong calculation
| > of string accumulator size.
| >
| > Many thanks Andreas Schwab and Geert Uytterhoeven for helping
| > to catch and fix the bug.
| >
| > Signed-off-by: Cyrill Gorcunov <[email protected]>
| > ---
| >
| > Index: linux-2.6.git/init/main.c
| > ===================================================================
| > --- linux-2.6.git.orig/init/main.c	2008-05-14 17:55:10.000000000 +0400
| > +++ linux-2.6.git/init/main.c	2008-05-14 19:11:18.000000000 +0400
| > @@ -702,7 +702,7 @@ static void __init do_initcalls(void)
| >
| >  	for (call = __initcall_start; call < __initcall_end; call++) {
| >  		ktime_t t0, t1, delta;
| > -		char msgbuf[40];
| > +		char msgbuf[64];
| >  		int result;
| >
| >  		if (initcall_debug) {
| > @@ -729,11 +729,11 @@ static void __init do_initcalls(void)
| >  			sprintf(msgbuf, "error code %d ", result);
| >
| >  		if (preempt_count() != count) {
| > -			strncat(msgbuf, "preemption imbalance ", sizeof(msgbuf));
| > +			strcat(msgbuf, "preemption imbalance ");
| >  			preempt_count() = count;
| >  		}
| >  		if (irqs_disabled()) {
| > -			strncat(msgbuf, "disabled interrupts ", sizeof(msgbuf));
| > +			strcat(msgbuf, "disabled interrupts ");
| >  			local_irq_enable();
| >  		}
| >  		if (msgbuf[0]) {
|
| umm, why can't m68k call strncat() from init/main.c??
|
Quoted 2 lines

there some problem with headers iirc, we have to declare it first or use some gcc option (as Adrian suggested). Actually I would prefer to use

gcc turns the strncat() into an implicit call to strlen() and some form of expanded memcpy(). E.g.

	if (preempt_count() != count) {
		strncat(msgbuf, "preemption imbalance ", sizeof(msgbuf));
		preempt_count() = count;
	}

becomes

        cmp.l 884(%a2),%d6      | <variable>.thread.info.preempt_count,
count
        jeq .L61        |
        move.l %d7,-(%sp)       | tmp76,
        jbsr strlen     |
        addq.l #4,%sp   |,
        move.l %d7,%a0  | tmp76, tmp80
        add.l %d0,%a0   |, tmp80
        move.l #1886545253,(%a0)+       |,
        move.l #1836086377,(%a0)+       |,
        move.l #1869488233,(%a0)+       |,
        move.l #1835164012,(%a0)+       |,
        move.l #1634624357,(%a0)+       |,
        move.w #8192,(%a0)      |,* D.28541
        move.l %d6,884(%a2)     | count,

<variable>.thread.info.preempt_count
.L61:

All other explicit calls to strlen() are inlined, as per include/asm-m68k/string.h.

Quoted 3 lines

strlcat there but it seems it would fail to build too. Originally I've messed
strlcat with strncat :(

Actually it build and runs fine after s/strncat/strlcat/...

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]

In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds

#5 lore raw
Quoted 93 lines · On Fri, 16 May 2008 00:22:14 +0400 "Cyrill Gorcunov" <[email protected]> wrote:
Quoted 91 lines · Geert Uytterhoeven
Quoted 55 lines · Cyrill Gorcunov

[Andrew Morton - Thu, May 15, 2008 at 10:58:03AM -0700]
| On Wed, 14 May 2008 19:44:02 +0400 Cyrill Gorcunov <[email protected]> wrote:
|
| > This patch does fix build bug on m68k wich does not have strncat in straight way.

| >
| > What is more important - my previous patch
| >
| > commit e662e1cfd434aa234b72fbc781f1d70211cb785b
| > Author: Cyrill Gorcunov <[email protected]>
| > Date:   Mon May 12 14:02:22 2008 -0700
| >
| >     init: don't lose initcall return values
| >
| > has introduced potential buffer overflow by wrong calculation
| > of string accumulator size.
| >
| > Many thanks Andreas Schwab and Geert Uytterhoeven for helping
| > to catch and fix the bug.
| >
| > Signed-off-by: Cyrill Gorcunov <[email protected]>
| > ---
| >
| > Index: linux-2.6.git/init/main.c
| > ===================================================================
| > --- linux-2.6.git.orig/init/main.c	2008-05-14 17:55:10.000000000 +0400
| > +++ linux-2.6.git/init/main.c	2008-05-14 19:11:18.000000000 +0400
| > @@ -702,7 +702,7 @@ static void __init do_initcalls(void)
| >
| >  	for (call = __initcall_start; call < __initcall_end; call++) {
| >  		ktime_t t0, t1, delta;
| > -		char msgbuf[40];
| > +		char msgbuf[64];
| >  		int result;
| >
| >  		if (initcall_debug) {
| > @@ -729,11 +729,11 @@ static void __init do_initcalls(void)
| >  			sprintf(msgbuf, "error code %d ", result);
| >
| >  		if (preempt_count() != count) {
| > -			strncat(msgbuf, "preemption imbalance ", sizeof(msgbuf));
| > +			strcat(msgbuf, "preemption imbalance ");
| >  			preempt_count() = count;
| >  		}
| >  		if (irqs_disabled()) {
| > -			strncat(msgbuf, "disabled interrupts ", sizeof(msgbuf));
| > +			strcat(msgbuf, "disabled interrupts ");
| >  			local_irq_enable();
| >  		}
| >  		if (msgbuf[0]) {
|
| umm, why can't m68k call strncat() from init/main.c??
|
Quoted 2 lines

there some problem with headers iirc, we have to declare it first or use some gcc option (as Adrian suggested). Actually I would prefer to use

gcc turns the strncat() into an implicit call to strlen() and some form of expanded memcpy(). E.g.

	if (preempt_count() != count) {
		strncat(msgbuf, "preemption imbalance ", sizeof(msgbuf));
		preempt_count() = count;
	}

becomes

        cmp.l 884(%a2),%d6      | <variable>.thread.info.preempt_count,
count
        jeq .L61        |
        move.l %d7,-(%sp)       | tmp76,
        jbsr strlen     |
        addq.l #4,%sp   |,
        move.l %d7,%a0  | tmp76, tmp80
        add.l %d0,%a0   |, tmp80
        move.l #1886545253,(%a0)+       |,
        move.l #1836086377,(%a0)+       |,
        move.l #1869488233,(%a0)+       |,
        move.l #1835164012,(%a0)+       |,
        move.l #1634624357,(%a0)+       |,
        move.w #8192,(%a0)      |,* D.28541
        move.l %d6,884(%a2)     | count,

<variable>.thread.info.preempt_count
.L61:

All other explicit calls to strlen() are inlined, as per include/asm-m68k/string.h.

Quoted 6 lines
Quoted 6 lines
Quoted 3 lines

strlcat there but it seems it would fail to build too. Originally I've messed
strlcat with strncat :(

Actually it build and runs fine after s/strncat/strlcat/...

(top-posting repaired)

Quoted 2 lines

Could you please make an update to the patch? I can make it only tomorrow evening (ie not that fast)

Like this?

From: Cyrill Gorcunov <[email protected]>

This patch fixes a build bug on m68k - gcc decides to emit a call to the strlen library function, which we don't implement. Use strlcat() instead.

What is more important - my previous patch

commit e662e1cfd434aa234b72fbc781f1d70211cb785b

Author: Cyrill Gorcunov <[email protected]>
Date:   Mon May 12 14:02:22 2008 -0700

init: don't lose initcall return values

Has introduced potential buffer overflow by wrong calculation of string accumulator size.

Many thanks Andreas Schwab and Geert Uytterhoeven for helping to catch and fix the bug.

---

 init/main.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
init/main.c renamed from init/main.c~init-fix-building-bug-and-potential-buffer-overflow +3 -3
diff -puN init/main.c~init-fix-building-bug-and-potential-buffer-overflow init/main.c
@@ -702,7 +702,7 @@ static void __init do_initcalls(void)
 
 	for (call = __initcall_start; call < __initcall_end; call++) {
 		ktime_t t0, t1, delta;
-		char msgbuf[40];
+		char msgbuf[64];
 		int result;
 
 		if (initcall_debug) {
@@ -729,11 +729,11 @@ static void __init do_initcalls(void)
 			sprintf(msgbuf, "error code %d ", result);
 
 		if (preempt_count() != count) {
-			strncat(msgbuf, "preemption imbalance ", sizeof(msgbuf));
+			strlcat(msgbuf, "preemption imbalance ", sizeof msgbuf);
 			preempt_count() = count;
 		}
 		if (irqs_disabled()) {
-			strncat(msgbuf, "disabled interrupts ", sizeof(msgbuf));
+			strlcat(msgbuf, "disabled interrupts ", sizeof msgbuf);
 			local_irq_enable();
 		}
 		if (msgbuf[0]) {

_

(yeah, I normally parenthesise sizeof too, but this provided 80-col salvation)

#6 lore raw
Quoted 3 lines · Andrew Morton

(yeah, I normally parenthesise sizeof too, but this provided 80-col salvation)

Why?

The nice way to provide 80-col salvation is to just fix the code. Instead of having complex nested loops, have a really trivial outer loop like

	for (call = __initcall_start; call < __initcall_end; call++)
		do_one_initcall(*call);

and then the code to actually do one of the initcalls is much simpler to read, and because it's not as indented, the 80-column issues just go away.

IOW, something like this (the diff looks ugly, but the end result is better).

Talking about cleanups, why the *hell* does print_fn_descriptor_symbol() take an "unsigned long", when every single user would want to give it a pointer?

Would somebody please want to move that cast into the macro (or better yet, make it an inline function that takes a 'void *'), and remove all the casts from the callers?

Linus

---
 init/main.c |   78 +++++++++++++++++++++++++++++++----------------------------
 1 files changed, 41 insertions(+), 37 deletions(-)
init/main.c +41 -37
index f406fef..0a1d65e 100644
@@ -695,53 +695,57 @@ __setup("initcall_debug", initcall_debug_setup);
 
 extern initcall_t __initcall_start[], __initcall_end[];
 
-static void __init do_initcalls(void)
+static void __init do_one_initcall(initcall_t call)
 {
-	initcall_t *call;
 	int count = preempt_count();
+	ktime_t t0, t1, delta;
+	char msgbuf[64];
+	int result;
+
+	if (initcall_debug) {
+		print_fn_descriptor_symbol("calling  %s()\n",
+				(unsigned long) call);
+		t0 = ktime_get();
+	}
 
-	for (call = __initcall_start; call < __initcall_end; call++) {
-		ktime_t t0, t1, delta;
-		char msgbuf[40];
-		int result;
+	result = call();
 
-		if (initcall_debug) {
-			print_fn_descriptor_symbol("calling  %s()\n",
-					(unsigned long) *call);
-			t0 = ktime_get();
-		}
+	if (initcall_debug) {
+		t1 = ktime_get();
+		delta = ktime_sub(t1, t0);
 
-		result = (*call)();
+		print_fn_descriptor_symbol("initcall %s()",
+				(unsigned long) call);
+		printk(" returned %d after %Ld msecs\n", result,
+			(unsigned long long) delta.tv64 >> 20);
+	}
 
-		if (initcall_debug) {
-			t1 = ktime_get();
-			delta = ktime_sub(t1, t0);
+	msgbuf[0] = 0;
 
-			print_fn_descriptor_symbol("initcall %s()",
-					(unsigned long) *call);
-			printk(" returned %d after %Ld msecs\n", result,
-				(unsigned long long) delta.tv64 >> 20);
-		}
+	if (result && result != -ENODEV && initcall_debug)
+		sprintf(msgbuf, "error code %d ", result);
 
-		msgbuf[0] = 0;
+	if (preempt_count() != count) {
+		strlcat(msgbuf, "preemption imbalance ", sizeof(msgbuf));
+		preempt_count() = count;
+	}
+	if (irqs_disabled()) {
+		strlcat(msgbuf, "disabled interrupts ", sizeof(msgbuf));
+		local_irq_enable();
+	}
+	if (msgbuf[0]) {
+		print_fn_descriptor_symbol(KERN_WARNING "initcall %s()",
+				(unsigned long) call);
+		printk(" returned with %s\n", msgbuf);
+	}
+}
 
-		if (result && result != -ENODEV && initcall_debug)
-			sprintf(msgbuf, "error code %d ", result);
+static void __init do_initcalls(void)
+{
+	initcall_t *call;
 
-		if (preempt_count() != count) {
-			strncat(msgbuf, "preemption imbalance ", sizeof(msgbuf));
-			preempt_count() = count;
-		}
-		if (irqs_disabled()) {
-			strncat(msgbuf, "disabled interrupts ", sizeof(msgbuf));
-			local_irq_enable();
-		}
-		if (msgbuf[0]) {
-			print_fn_descriptor_symbol(KERN_WARNING "initcall %s()",
-					(unsigned long) *call);
-			printk(" returned with %s\n", msgbuf);
-		}
-	}
+	for (call = __initcall_start; call < __initcall_end; call++)
+		do_one_initcall(*call);
 
 	/* Make sure there is no pending stuff from the initcall sequence */
 	flush_scheduled_work();
#7 lore raw
Quoted 8 lines · On Thu, 15 May 2008 14:15:38 -0700 (PDT) Linus Torvalds…
Quoted 3 lines · Andrew Morton

(yeah, I normally parenthesise sizeof too, but this provided 80-col salvation)

Why?

this, basically:

Quoted 2 lines
 init/main.c |   78 +++++++++++++++++++++++++++++++----------------------------
 1 files changed, 41 insertions(+), 37 deletions(-)

the dont-mix-bugfixes-and-cleanups mantra.

The patch looks good to me and compiles cleanly on various architectures.

Quoted 3 lines

Talking about cleanups, why the *hell* does print_fn_descriptor_symbol() take an "unsigned long", when every single user would want to give it a pointer?

Yes, we make that mistake fairly regularly (looks at timer_list.data). We start out not being sure whether most callers will pass in a ulong or a pointer and guess wrongly.

Quoted 3 lines

Would somebody please want to move that cast into the macro (or better yet, make it an inline function that takes a 'void *'), and remove all the casts from the callers?

Would be nice.

#10 lore raw
In reply to Linus Torvalds
Quoted 3 lines · Linus Torvalds

Talking about cleanups, why the *hell* does print_fn_descriptor_symbol() take an "unsigned long", when every single user would want to give it a pointer?

Would somebody please want to move that cast into the macro (or better yet, make it an inline function that takes a 'void *'), and remove all the casts from the callers?

[ ... ]

Review

Quoted 2 lines
(quoted diff) +2 -0
+		print_fn_descriptor_symbol("calling  %s()\n",
+				(unsigned long) call);

And while that person is at it, could he or she please remove the silly () from the "foo+0x0/0x1234()" (or the "foo+0x0/0x1234 [bar]()" or the "0x12345678()").

Rene.

#8 lore raw

PATCH 1/1 Add a void * alternative to print_fn_descriptor_symbol()

In reply to Andrew Morton
Quoted 6 lines · At 2008-05-15 14:45:54 -0700, [email protected] wrote:
Quoted 4 lines

Would somebody please want to move that cast into the macro (or better yet, make it an inline function that takes a 'void *'), and remove all the casts from the callers?

Would be nice.

Something like this?

-- ams

All the callers of print_fn_descriptor_symbol() had to cast their void * argument to unsigned long. This patch adds an inline print_fn_symbolic() that takes a void * directly, and updates the callers to use it instead.

---
 include/linux/kallsyms.h  |   10 ++++++++++
 drivers/base/power/main.c |    2 +-
 drivers/pci/quirks.c      |    3 +--
 drivers/pnp/quirks.c      |    3 +--
 init/main.c               |    9 +++------
 5 files changed, 16 insertions(+), 11 deletions(-)
include/linux/kallsyms.h +10 -0
index 82de2fb..ed8ab42 100644
@@ -101,6 +101,16 @@ static inline void print_symbol(const char *fmt, unsigned long addr)
 		       __builtin_extract_return_addr((void *)addr));
 }
 
+static inline void print_fn_symbolic(const char *fmt, const void *addr)
+{
+#if defined(CONFIG_IA64) || defined(CONFIG_PPC64)
+	unsigned long *faddr = (unsigned long *)addr;
+	print_symbol(fmt, faddr[0]);
+#else
+	print_symbol(fmt, (unsigned long)addr);
+#endif
+}
+
 #ifndef CONFIG_64BIT
 #define print_ip_sym(ip)		\
 do {					\
drivers/base/power/main.c +1 -1
index 7b76fd3..9625317 100644
@@ -418,7 +418,7 @@ void __suspend_report_result(const char *function, void *fn, int ret)
 {
 	if (ret) {
 		printk(KERN_ERR "%s(): ", function);
-		print_fn_descriptor_symbol("%s() returns ", (unsigned long)fn);
+		print_fn_symbolic("%s returns ", fn);
 		printk("%d\n", ret);
 	}
 }
drivers/pci/quirks.c +1 -2
index f2d9c77..12d07eb 100644
@@ -1503,8 +1503,7 @@ static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_f
  		    (f->device == dev->device || f->device == (u16) PCI_ANY_ID)) {
 #ifdef DEBUG
 			dev_dbg(&dev->dev, "calling ");
-			print_fn_descriptor_symbol("%s()\n",
-				(unsigned long) f->hook);
+			print_fn_symbolic("%s\n", f->hook);
 #endif
 			f->hook(dev);
 		}
drivers/pnp/quirks.c +1 -2
index ffdb12a..f84d79f 100644
@@ -331,8 +331,7 @@ void pnp_fixup_device(struct pnp_dev *dev)
 			continue;
 #ifdef DEBUG
 		dev_dbg(&dev->dev, "%s: calling ", f->id);
-		print_fn_descriptor_symbol("%s\n",
-				(unsigned long) f->quirk_function);
+		print_fn_symbolic("%s\n", f->quirk_function);
 #endif
 		f->quirk_function(dev);
 	}
init/main.c +3 -6
index f406fef..c456ca8 100644
@@ -706,8 +706,7 @@ static void __init do_initcalls(void)
 		int result;
 
 		if (initcall_debug) {
-			print_fn_descriptor_symbol("calling  %s()\n",
-					(unsigned long) *call);
+			print_fn_symbolic("calling %s\n", *call);
 			t0 = ktime_get();
 		}
 
@@ -717,8 +716,7 @@ static void __init do_initcalls(void)
 			t1 = ktime_get();
 			delta = ktime_sub(t1, t0);
 
-			print_fn_descriptor_symbol("initcall %s()",
-					(unsigned long) *call);
+			print_fn_symbolic("initcall %s", *call);
 			printk(" returned %d after %Ld msecs\n", result,
 				(unsigned long long) delta.tv64 >> 20);
 		}
@@ -737,8 +735,7 @@ static void __init do_initcalls(void)
 			local_irq_enable();
 		}
 		if (msgbuf[0]) {
-			print_fn_descriptor_symbol(KERN_WARNING "initcall %s()",
-					(unsigned long) *call);
+			print_fn_symbolic(KERN_WARNING "initcall %s", *call);
 			printk(" returned with %s\n", msgbuf);
 		}
 	}
Signature · 1 line
1.5.5.1
#9 lore raw
In reply to Andrew Morton
Quoted 7 lines · Andrew Morton

this, basically:

Quoted 2 lines
 init/main.c |   78 +++++++++++++++++++++++++++++++----------------------------
 1 files changed, 41 insertions(+), 37 deletions(-)

the dont-mix-bugfixes-and-cleanups mantra.

Sure. I committed them as two separate things.

The point *I* had was that we don't make source code uglier for arbitrary reasons. The checkpatch.pl script shouldn't be powerful enough that we do uglier source code and break arbitrary rules just to make that script happy.

So either we should sy "screw the script, it's wrong", or we should just not fix the bug. Or we should say "ok, I can write even _better_ source code, and fix the bug, make the source look nicer _and_ not piss off the script too".

Quoted 5 lines
Quoted 3 lines

Would somebody please want to move that cast into the macro (or better yet, make it an inline function that takes a 'void *'), and remove all the casts from the callers?

Would be nice.

So I did that too.

Linus

#11 lore raw
In reply to Andrew Morton

Yes! Exactly! Thanks, Andrew! (i didn't look into what Linus suggested 'cause i just waked up and have to go to my job)

Quoted 175 lines · Andrew Morton
Quoted 96 lines · On Fri, 16 May 2008 00:22:14 +0400 "Cyrill Gorcunov" <[email protected]> wrote:
Quoted 94 lines · Geert Uytterhoeven
Quoted 57 lines · Cyrill Gorcunov

[Andrew Morton - Thu, May 15, 2008 at 10:58:03AM -0700]
| On Wed, 14 May 2008 19:44:02 +0400 Cyrill Gorcunov <[email protected]>
wrote:
|
| > This patch does fix build bug on m68k wich does not have strncat in straight way.

| >
| > What is more important - my previous patch
| >
| > commit e662e1cfd434aa234b72fbc781f1d70211cb785b
| > Author: Cyrill Gorcunov <[email protected]>
| > Date:   Mon May 12 14:02:22 2008 -0700
| >
| >     init: don't lose initcall return values
| >
| > has introduced potential buffer overflow by wrong calculation
| > of string accumulator size.
| >
| > Many thanks Andreas Schwab and Geert Uytterhoeven for helping
| > to catch and fix the bug.
| >
| > Signed-off-by: Cyrill Gorcunov <[email protected]>
| > ---
| >
| > Index: linux-2.6.git/init/main.c
| > ===================================================================
| > --- linux-2.6.git.orig/init/main.c	2008-05-14 17:55:10.000000000
+0400
| > +++ linux-2.6.git/init/main.c	2008-05-14 19:11:18.000000000 +0400
| > @@ -702,7 +702,7 @@ static void __init do_initcalls(void)
| >
| >  	for (call = __initcall_start; call < __initcall_end; call++) {
| >  		ktime_t t0, t1, delta;
| > -		char msgbuf[40];
| > +		char msgbuf[64];
| >  		int result;
| >
| >  		if (initcall_debug) {
| > @@ -729,11 +729,11 @@ static void __init do_initcalls(void)
| >  			sprintf(msgbuf, "error code %d ", result);
| >
| >  		if (preempt_count() != count) {
| > -			strncat(msgbuf, "preemption imbalance ", sizeof(msgbuf));
| > +			strcat(msgbuf, "preemption imbalance ");
| >  			preempt_count() = count;
| >  		}
| >  		if (irqs_disabled()) {
| > -			strncat(msgbuf, "disabled interrupts ", sizeof(msgbuf));
| > +			strcat(msgbuf, "disabled interrupts ");
| >  			local_irq_enable();
| >  		}
| >  		if (msgbuf[0]) {
|
| umm, why can't m68k call strncat() from init/main.c??
|
Quoted 3 lines

there some problem with headers iirc, we have to declare it first or use some gcc option (as Adrian suggested). Actually I would prefer to use

gcc turns the strncat() into an implicit call to strlen() and some form of expanded memcpy(). E.g.

	if (preempt_count() != count) {
		strncat(msgbuf, "preemption imbalance ", sizeof(msgbuf));
		preempt_count() = count;
	}

becomes

        cmp.l 884(%a2),%d6      | <variable>.thread.info.preempt_count,
count
        jeq .L61        |
        move.l %d7,-(%sp)       | tmp76,
        jbsr strlen     |
        addq.l #4,%sp   |,
        move.l %d7,%a0  | tmp76, tmp80
        add.l %d0,%a0   |, tmp80
        move.l #1886545253,(%a0)+       |,
        move.l #1836086377,(%a0)+       |,
        move.l #1869488233,(%a0)+       |,
        move.l #1835164012,(%a0)+       |,
        move.l #1634624357,(%a0)+       |,
        move.w #8192,(%a0)      |,* D.28541
        move.l %d6,884(%a2)     | count,

<variable>.thread.info.preempt_count
.L61:

All other explicit calls to strlen() are inlined, as per include/asm-m68k/string.h.

Quoted 6 lines
Quoted 6 lines
Quoted 3 lines

strlcat there but it seems it would fail to build too. Originally I've messed
strlcat with strncat :(

Actually it build and runs fine after s/strncat/strlcat/...

(top-posting repaired)

Quoted 2 lines

Could you please make an update to the patch? I can make it only tomorrow evening (ie not that fast)

Like this?

From: Cyrill Gorcunov <[email protected]>

This patch fixes a build bug on m68k - gcc decides to emit a call to the strlen library function, which we don't implement. Use strlcat() instead.

What is more important - my previous patch

commit e662e1cfd434aa234b72fbc781f1d70211cb785b

Author: Cyrill Gorcunov <[email protected]>
Date:   Mon May 12 14:02:22 2008 -0700

init: don't lose initcall return values

Has introduced potential buffer overflow by wrong calculation of string accumulator size.

Many thanks Andreas Schwab and Geert Uytterhoeven for helping to catch and fix the bug.

---

 init/main.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff -puN init/main.c~init-fix-building-bug-and-potential-buffer-overflow init/main.c

init/main.c renamed from init/main.c~init-fix-building-bug-and-potential-buffer-overflow +3 -3
@@ -702,7 +702,7 @@ static void __init do_initcalls(void)
 
 	for (call = __initcall_start; call < __initcall_end; call++) {
 		ktime_t t0, t1, delta;
-		char msgbuf[40];
+		char msgbuf[64];
 		int result;
 
 		if (initcall_debug) {
@@ -729,11 +729,11 @@ static void __init do_initcalls(void)
 			sprintf(msgbuf, "error code %d ", result);
 
 		if (preempt_count() != count) {
-			strncat(msgbuf, "preemption imbalance ", sizeof(msgbuf));
+			strlcat(msgbuf, "preemption imbalance ", sizeof msgbuf);
 			preempt_count() = count;
 		}
 		if (irqs_disabled()) {
-			strncat(msgbuf, "disabled interrupts ", sizeof(msgbuf));
+			strlcat(msgbuf, "disabled interrupts ", sizeof msgbuf);
 			local_irq_enable();
 		}
 		if (msgbuf[0]) {

_

(yeah, I normally parenthesise sizeof too, but this provided 80-col salvation)

#12 lore raw
Quoted 3 lines · Cyrill Gorcunov

Yes! Exactly! Thanks, Andrew! (i didn't look into what Linus suggested 'cause i just waked up and have to go to my job)

[...]

And sorry about top-posting (gmail mobile client is really screwed up, trying to force top-post all the time)

#13 lore raw
In reply to Andrew Morton
Quoted 14 lines · Andrew Morton
Quoted 11 lines · On Fri, 16 May 2008 00:22:14 +0400 "Cyrill Gorcunov" <[email protected]> wrote:
Quoted 10 lines · Geert Uytterhoeven
Quoted 6 lines · Cyrill Gorcunov

[Andrew Morton - Thu, May 15, 2008 at 10:58:03AM -0700]
| On Wed, 14 May 2008 19:44:02 +0400 Cyrill Gorcunov <[email protected]> wrote:
strlcat there but it seems it would fail to build too. Originally I've messed
strlcat with strncat :(

Actually it build and runs fine after s/strncat/strlcat/...

Quoted 6 lines

(top-posting repaired)

Quoted 2 lines

Could you please make an update to the patch? I can make it only tomorrow evening (ie not that fast)

Like this?

Builds and boots fine!

Quoted 17 lines

From: Cyrill Gorcunov <[email protected]>

This patch fixes a build bug on m68k - gcc decides to emit a call to the strlen library function, which we don't implement. Use strlcat() instead.

What is more important - my previous patch

commit e662e1cfd434aa234b72fbc781f1d70211cb785b

Author: Cyrill Gorcunov <[email protected]>
Date:   Mon May 12 14:02:22 2008 -0700

init: don't lose initcall return values

Has introduced potential buffer overflow by wrong calculation of string accumulator size.

Quoted 6 lines

Many thanks Andreas Schwab and Geert Uytterhoeven for helping to catch and fix the bug.

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]

In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds