Skip to contentSkip to conversation

Fix NR_KEYS off-by-one error

PATCH In review OGAWA Hirofumi 5 participants 25 messages Jul 16, 2004 – Jul 30, 2004 Char and misc drivers

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Fix NR_KEYS off-by-one error

KDGKBENT ioctl can use 256 entries (0-255), but it was defined as key_map[NR_KEYS] (NR_KEYS == 255). The code seems also thinking it's 256.

	key_map[0] = U(K_ALLOCATED);
	for (j = 1; j < NR_KEYS; j++)
		key_map[j] = U(K_HOLE);

---

 include/linux/keyboard.h |    2 +-
 1 files changed, 1 insertion(+), 1 deletion(-)
include/linux/keyboard.h renamed from include/linux/keyboard.h~nr_keys-off-by-one +1 -1
diff -puN include/linux/keyboard.h~nr_keys-off-by-one include/linux/keyboard.h
@@ -16,7 +16,7 @@
 
 #define NR_SHIFT	9
 
-#define NR_KEYS		255
+#define NR_KEYS		256
 #define MAX_NR_KEYMAPS	256
 /* This means 128Kb if all keymaps are allocated. Only the superuser
 	may increase the number of keymaps beyond MAX_NR_OF_USER_KEYMAPS. */

_

#1 lore raw
Quoted 6 lines · OGAWA Hirofumi

KDGKBENT ioctl can use 256 entries (0-255), but it was defined as key_map[NR_KEYS] (NR_KEYS == 255). The code seems also thinking it's 256.

	key_map[0] = U(K_ALLOCATED);
	for (j = 1; j < NR_KEYS; j++)
		key_map[j] = U(K_HOLE);

The patch below might cause problems, though, because some apps may (in old versions are) using a char variable to index up to NR_KEYS, which leads to an endless loop.

Quoted 21 lines

---

 include/linux/keyboard.h |    2 +-
 1 files changed, 1 insertion(+), 1 deletion(-)

diff -puN include/linux/keyboard.h~nr_keys-off-by-one include/linux/keyboard.h

include/linux/keyboard.h renamed from include/linux/keyboard.h~nr_keys-off-by-one +1 -1
@@ -16,7 +16,7 @@
 
 #define NR_SHIFT	9
 
-#define NR_KEYS		255
+#define NR_KEYS		256
 #define MAX_NR_KEYMAPS	256
 /* This means 128Kb if all keymaps are allocated. Only the superuser
 	may increase the number of keymaps beyond MAX_NR_OF_USER_KEYMAPS. */

_

Signature · 2 lines
Vojtech Pavlik
SuSE Labs, SuSE CR
#2 lore raw
Quoted 11 lines · Vojtech Pavlik
Quoted 6 lines · OGAWA Hirofumi

KDGKBENT ioctl can use 256 entries (0-255), but it was defined as key_map[NR_KEYS] (NR_KEYS == 255). The code seems also thinking it's 256.

	key_map[0] = U(K_ALLOCATED);
	for (j = 1; j < NR_KEYS; j++)
		key_map[j] = U(K_HOLE);

The patch below might cause problems, though, because some apps may (in old versions are) using a char variable to index up to NR_KEYS, which leads to an endless loop.

Maybe. But isn't it just bug of apps?

Signature · 1 line
OGAWA Hirofumi <[email protected]>
#3 lore raw
In reply to Vojtech Pavlik

On Sat, Jul 17, 2004 at 01:35:59AM +0900, OGAWA Hirofumi wrote:

:: KDGKBENT ioctl can use 256 entries (0-255), but it was defined as :: key_map[NR_KEYS] (NR_KEYS == 255). The code seems also thinking it's 256. ::
:: key_map[0] = U(K_ALLOCATED);
:: for (j = 1; j < NR_KEYS; j++)
:: key_map[j] = U(K_HOLE);

I think the code has no opinion. It was 128 in 2.4. I am not aware of assumptions on NR_KEYS. So, do not think this is an off-by-one error. Vojtech did this intentionally.

However, I have no objections. In fact loadkeys uses 256.

Quoted 3 lines · Vojtech Pavlik

The patch might cause problems, though, because some apps may (in old versions are) using a char variable to index up to NR_KEYS, which leads to an endless loop.

The binaries will still work. If the utility is recompiled, against recent kernel headers, then the person doing that is responsible for the result.

I just checked kbd, but there are no such char variables there. Do you have specific utilities in mind? Is X OK?

Andries

#4 lore raw
Quoted 9 lines · Andries Brouwer

On Sat, Jul 17, 2004 at 01:35:59AM +0900, OGAWA Hirofumi wrote:

:: KDGKBENT ioctl can use 256 entries (0-255), but it was defined as :: key_map[NR_KEYS] (NR_KEYS == 255). The code seems also thinking it's 256. ::
:: key_map[0] = U(K_ALLOCATED);
:: for (j = 1; j < NR_KEYS; j++)
:: key_map[j] = U(K_HOLE);

Quoted 3 lines

I think the code has no opinion. It was 128 in 2.4. I am not aware of assumptions on NR_KEYS. So, do not think this is an off-by-one error.

My point is that key_map is 0-254 array. But KDGKBENT uses 255

	case KDGKBENT:
		key_map = key_maps[s];
		if (key_map) {
		    val = U(key_map[i]);
		    if (kbd->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES)
			val = K_HOLE;
		} else
		    val = (i ? K_HOLE : K_NOSUCHMAP);
		return put_user(val, &user_kbe->kb_value);

Thanks.

Signature · 1 line
OGAWA Hirofumi <[email protected]>
#5 lore raw
Quoted 18 lines · OGAWA Hirofumi
Quoted 9 lines · Andries Brouwer

On Sat, Jul 17, 2004 at 01:35:59AM +0900, OGAWA Hirofumi wrote:

:: KDGKBENT ioctl can use 256 entries (0-255), but it was defined as :: key_map[NR_KEYS] (NR_KEYS == 255). The code seems also thinking it's 256. ::
:: key_map[0] = U(K_ALLOCATED);
:: for (j = 1; j < NR_KEYS; j++)
:: key_map[j] = U(K_HOLE);

Quoted 3 lines

I think the code has no opinion. It was 128 in 2.4. I am not aware of assumptions on NR_KEYS. So, do not think this is an off-by-one error.

My point is that key_map is 0-254 array. But KDGKBENT uses 255

Quoted 10 lines
	case KDGKBENT:
		key_map = key_maps[s];
		if (key_map) {
		    val = U(key_map[i]);
		    if (kbd->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES)
			val = K_HOLE;
		} else
		    val = (i ? K_HOLE : K_NOSUCHMAP);
		return put_user(val, &user_kbe->kb_value);

This all seems a bit inconclusive. Do we proceed with the original patch or not? If not, how do we fix the overflow which Hirofumi has identified?

#6 lore raw
Quoted 30 lines · Andrew Morton
Quoted 18 lines · OGAWA Hirofumi
Quoted 9 lines · Andries Brouwer

On Sat, Jul 17, 2004 at 01:35:59AM +0900, OGAWA Hirofumi wrote:

:: KDGKBENT ioctl can use 256 entries (0-255), but it was defined as :: key_map[NR_KEYS] (NR_KEYS == 255). The code seems also thinking it's 256. ::
:: key_map[0] = U(K_ALLOCATED);
:: for (j = 1; j < NR_KEYS; j++)
:: key_map[j] = U(K_HOLE);

Quoted 3 lines

I think the code has no opinion. It was 128 in 2.4. I am not aware of assumptions on NR_KEYS. So, do not think this is an off-by-one error.

My point is that key_map is 0-254 array. But KDGKBENT uses 255

Quoted 10 lines
	case KDGKBENT:
		key_map = key_maps[s];
		if (key_map) {
		    val = U(key_map[i]);
		    if (kbd->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES)
			val = K_HOLE;
		} else
		    val = (i ? K_HOLE : K_NOSUCHMAP);
		return put_user(val, &user_kbe->kb_value);
Quoted 2 lines

This all seems a bit inconclusive. Do we proceed with the original patch or not? If not, how do we fix the overflow which Hirofumi has identified?

I think we should check the value in the ioctl, regardless of what's NR_KEYS defined to.

Signature · 2 lines
Vojtech Pavlik
SuSE Labs, SuSE CR
#7 lore raw
Quoted 5 lines · Vojtech Pavlik
Quoted 2 lines

This all seems a bit inconclusive. Do we proceed with the original patch or not? If not, how do we fix the overflow which Hirofumi has identified?

I think we should check the value in the ioctl, regardless of what's NR_KEYS defined to.

However, it breaks the current binary instead. (at least console-tools, kbdutils).

Signature · 1 line
OGAWA Hirofumi <[email protected]>
#8 lore raw
Quoted 10 lines · OGAWA Hirofumi
Quoted 5 lines · Vojtech Pavlik
Quoted 2 lines

This all seems a bit inconclusive. Do we proceed with the original patch or not? If not, how do we fix the overflow which Hirofumi has identified?

I think we should check the value in the ioctl, regardless of what's NR_KEYS defined to.

However, it breaks the current binary instead. (at least console-tools, kbdutils).

We can do both, then, if that helps.

Signature · 2 lines
Vojtech Pavlik
SuSE Labs, SuSE CR
#9 lore raw
Quoted 7 lines · Vojtech Pavlik
Quoted 5 lines · OGAWA Hirofumi
Quoted 3 lines · Vojtech Pavlik
Quoted 2 lines

This all seems a bit inconclusive. Do we proceed with the original patch or not? If not, how do we fix the overflow which Hirofumi has identified?

Quoted 7 lines
Quoted 5 lines
Quoted 2 lines

I think we should check the value in the ioctl, regardless of what's NR_KEYS defined to.

However, it breaks the current binary instead. (at least console-tools, kbdutils).

We can do both, then, if that helps.

I'm confused. Sorry.

What is meaning of both? The following patch? If so, "if (i >= NR_KEYS)" part is never true, because "i" is unsigned char.

Signature · 27 lines
OGAWA Hirofumi <[email protected]>

diff -puN include/linux/keyboard.h~nr_keys-off-by-one include/linux/keyboard.h
--- linux-2.6.8-rc2/include/linux/keyboard.h~nr_keys-off-by-one	2004-07-26 00:26:59.000000000 +0900
+++ linux-2.6.8-rc2-hirofumi/include/linux/keyboard.h	2004-07-26 00:26:59.000000000 +0900
@@ -16,7 +16,7 @@
 
 #define NR_SHIFT	9
 
-#define NR_KEYS		255
+#define NR_KEYS		256
 #define MAX_NR_KEYMAPS	256
 /* This means 128Kb if all keymaps are allocated. Only the superuser
 	may increase the number of keymaps beyond MAX_NR_OF_USER_KEYMAPS. */
diff -puN drivers/char/vt_ioctl.c~nr_keys-off-by-one drivers/char/vt_ioctl.c
--- linux-2.6.8-rc2/drivers/char/vt_ioctl.c~nr_keys-off-by-one	2004-07-28 03:18:43.000000000 +0900
+++ linux-2.6.8-rc2-hirofumi/drivers/char/vt_ioctl.c	2004-07-28 03:22:24.000000000 +0900
@@ -82,6 +82,8 @@ do_kdsk_ioctl(int cmd, struct kbentry __
 
 	if (copy_from_user(&tmp, user_kbe, sizeof(struct kbentry)))
 		return -EFAULT;
+	if (i >= NR_KEYS)
+		return -EINVAL;
 
 	switch (cmd) {
 	case KDGKBENT:
_
#10 lore raw
In reply to OGAWA Hirofumi
Quoted 11 lines · OGAWA Hirofumi
Quoted 10 lines

:: KDGKBENT ioctl can use 256 entries (0-255), but it was defined as :: key_map[NR_KEYS] (NR_KEYS == 255). The code seems also thinking it's 256. ::
:: key_map[0] = U(K_ALLOCATED);
:: for (j = 1; j < NR_KEYS; j++)
:: key_map[j] = U(K_HOLE);

I think the code has no opinion. It was 128 in 2.4. I am not aware of assumptions on NR_KEYS. So, do not think this is an off-by-one error.

Quoted 6 lines

My point is that key_map is 0-254 array. But KDGKBENT uses 255

	case KDGKBENT:
		key_map = key_maps[s];
		if (key_map) {
		    val = U(key_map[i]);

Hmm. Yes.

In 2.4 the preceding code is

        if (i >= NR_KEYS || s >= MAX_NR_KEYMAPS)
                return -EINVAL;

It looks like somebody removed this test in 2.6. Bad. No doubt an error caused by "fixing" gcc warnings. Shame on akpm.

When an array has an arbitrary upper bound that can be changed via a #define, and for some values of the upper bound a test is superfluous, that does not mean that the test is superfluous.

Andries

#11 lore raw
Quoted 3 lines · Andries Brouwer

When an array has an arbitrary upper bound that can be changed via a #define, and for some values of the upper bound a test is superfluous, that does not mean that the test is superfluous.

OK. The patch is the following.

Any comments or suggestions?

Signature · 48 lines
OGAWA Hirofumi <[email protected]>


[PATCH] Fix NR_KEYS off-by-one error

KDGKBENT ioctl can use 256 entries (0-255), but it was defined as
key_map[NR_KEYS] (NR_KEYS == 255). The code seems also thinking it's 256.

	key_map[0] = U(K_ALLOCATED);
	for (j = 1; j < NR_KEYS; j++)
		key_map[j] = U(K_HOLE);

Signed-off-by: OGAWA Hirofumi <[email protected]>
---

 drivers/char/vt_ioctl.c  |    6 ++++++
 include/linux/keyboard.h |    2 +-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff -puN include/linux/keyboard.h~nr_keys-off-by-one include/linux/keyboard.h
--- linux-2.6.8-rc2/include/linux/keyboard.h~nr_keys-off-by-one	2004-07-28 03:37:12.000000000 +0900
+++ linux-2.6.8-rc2-hirofumi/include/linux/keyboard.h	2004-07-28 03:37:12.000000000 +0900
@@ -16,7 +16,7 @@
 
 #define NR_SHIFT	9
 
-#define NR_KEYS		255
+#define NR_KEYS		256
 #define MAX_NR_KEYMAPS	256
 /* This means 128Kb if all keymaps are allocated. Only the superuser
 	may increase the number of keymaps beyond MAX_NR_OF_USER_KEYMAPS. */
diff -puN drivers/char/vt_ioctl.c~nr_keys-off-by-one drivers/char/vt_ioctl.c
--- linux-2.6.8-rc2/drivers/char/vt_ioctl.c~nr_keys-off-by-one	2004-07-29 01:31:12.000000000 +0900
+++ linux-2.6.8-rc2-hirofumi/drivers/char/vt_ioctl.c	2004-07-29 01:35:23.000000000 +0900
@@ -83,6 +83,12 @@ do_kdsk_ioctl(int cmd, struct kbentry __
 	if (copy_from_user(&tmp, user_kbe, sizeof(struct kbentry)))
 		return -EFAULT;
 
+#if NR_KEYS != 256 || MAX_NR_KEYMAPS != 256
+#error "you should check this too"
+	if (i >= NR_KEYS || s >= MAX_NR_KEYMAPS)
+		return -EINVAL;
+#endif
+
 	switch (cmd) {
 	case KDGKBENT:
 		key_map = key_maps[s];
_
#12 lore raw
Quoted 1 line · OGAWA Hirofumi

Any comments or suggestions?

How about coding more of this in C instead of in C preprocessor:

drivers/char/vt_ioctl.c +11 -6
@@ -71,18 +71,26 @@ unsigned char keyboard_type = KB_101;
 #define GPLAST 0x3df
 #define GPNUM (GPLAST - GPFIRST + 1)
 
-#define i (tmp.kb_index)
-#define s (tmp.kb_table)
-#define v (tmp.kb_value)
 static inline int
 do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm, struct kbd_struct *kbd)
 {
 	struct kbentry tmp;
 	ushort *key_map, val, ov;
+	unsigned char s, i;
+	unsigned short v;
 
 	if (copy_from_user(&tmp, user_kbe, sizeof(struct kbentry)))
 		return -EFAULT;
 
+	s = tmp.kb_table;
+	i = tmp.kb_index;
+	v = tmp.kb_value;
+
+	if (s >= ARRAY_SIZE(key_maps))
+		return -EINVAL;
+	if (i >= ARRAY_SIZE(key_map))
+		return -EINVAL;
+
 	switch (cmd) {
 	case KDGKBENT:
 		key_map = key_maps[s];
@@ -155,9 +163,6 @@ do_kdsk_ioctl(int cmd, struct kbentry __
 	}
 	return 0;
 }
-#undef i
-#undef s
-#undef v
 
 static inline int 
 do_kbkeycode_ioctl(int cmd, struct kbkeycode __user *user_kbkc, int perm)
Signature · 3 lines
                          I won't rest till it's the best ...
                          Programmer, Linux Scalability
                          Paul Jackson <[email protected]> 1.650.933.1373
#13 lore raw
Quoted 7 lines · Paul Jackson
drivers/char/vt_ioctl.c +0 -3
-#define i (tmp.kb_index)
-#define s (tmp.kb_table)
-#define v (tmp.kb_value)
 static inline int
 do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm, struct kbd_struct *kbd)
 {
 	struct kbentry tmp;

drivers/char/vt_ioctl.c unsigned char keyboard_type = KB_101; · line 87

Quoted 10 lines
drivers/char/vt_ioctl.c +5 -0
 	ushort *key_map, val, ov;
+	unsigned char s, i;
+	unsigned short v;
 
 	if (copy_from_user(&tmp, user_kbe, sizeof(struct kbentry)))
 		return -EFAULT;
 
+	s = tmp.kb_table;
+	i = tmp.kb_index;
+	v = tmp.kb_value;

Yes, s/i/v macro is ugly. But I think it shouldn't, because it limits the range when struct kbentry was changed. (I think this change is likely)

Perhaps only expand the macro... hmm..

drivers/char/vt_ioctl.c unsigned char keyboard_type = KB_101; · line 92

Quoted 4 lines
drivers/char/vt_ioctl.c +4 -0
+	if (s >= ARRAY_SIZE(key_maps))
+		return -EINVAL;
+	if (i >= ARRAY_SIZE(key_map))
+		return -EINVAL;

key_map is pointer, so ARRAY_SIZE() can't use. Anyhow these will be warned by gcc.

Although overhead is insignificance, I'd hated to add overhead of this test because test is not needed right now.

Signature · 1 line
OGAWA Hirofumi <[email protected]>
#14 lore raw

Thank-you for considering my comments.

Quoted 2 lines · OGAWA

because it limits the range when struct kbentry
was changed. (I think this change is likely)

I'm not sure I understand this comment -- but I am guessing that you mean that:

drivers/char/vt_ioctl.c unsigned char keyboard_type = KB_101; · line 80

Quoted 2 lines
drivers/char/vt_ioctl.c +2 -0
+	unsigned char s, i;
+	unsigned short v;

would limit s, i, and v if struct kbentry was changed to have larger types (short or int, say) for these.

Good point.

Would it work to use larger types for local variables s, i, and v now, in order to avoid the ugly macro, as in:

	unsigned int s, i, v;

However, if I have guessed incorrectly, then this idea may make no sense. If so, sorry about that.

Quoted 1 line

key_map is pointer, so ARRAY_SIZE() can't use.

Yes - good point.

Quoted 1 line

Anyhow these will be warned by gcc.

If larger types, as I wrote above, were used for s, i, and v, then does gcc still warn?

Quoted 2 lines

Although overhead is insignificance, I'd hated to add overhead of this test because test is not needed right now.

Code clarity matters most here. If the code had been crystal clear to the casual reader, then the initial mistake, of removing the range checking, probably would never have occurred in the first place, and we human beings would have already saved more time than we can ever hope to save by optimizing this code.

You are absolutely correct that overhead is insignificant.

But code clarity - that is very significant <smile>.

Let all the essential details be spelled out, in the simplest most easily read, C statements that can be found to express it.

Each line of code we put in the kernel will be read by many people doing various things. They will be more likely to have a correct understanding of our code if it is clear and simple, with a minimum of surprises.

Signature · 3 lines
                          I won't rest till it's the best ...
                          Programmer, Linux Scalability
                          Paul Jackson <[email protected]> 1.650.933.1373
#15 lore raw
Quoted 6 lines · Paul Jackson

drivers/char/vt_ioctl.c unsigned char keyboard_type = KB_101; · line 80

Quoted 2 lines
drivers/char/vt_ioctl.c +2 -0
+	unsigned char s, i;
+	unsigned short v;

would limit s, i, and v if struct kbentry was changed to have larger types (short or int, say) for these.

Quoted 6 lines

Good point.

Would it work to use larger types for local variables s, i, and v now, in order to avoid the ugly macro, as in:

	unsigned int s, i, v;

Yes.

Quoted 4 lines
Quoted 1 line

Anyhow these will be warned by gcc.

If larger types, as I wrote above, were used for s, i, and v, then does gcc still warn?

Probably gcc not warn, I think.

Quoted 13 lines
Quoted 2 lines

Although overhead is insignificance, I'd hated to add overhead of this test because test is not needed right now.

Code clarity matters most here. If the code had been crystal clear to the casual reader, then the initial mistake, of removing the range checking, probably would never have occurred in the first place, and we human beings would have already saved more time than we can ever hope to save by optimizing this code.

You are absolutely correct that overhead is insignificant.

But code clarity - that is very significant <smile>.

Quoted 7 lines

Let all the essential details be spelled out, in the simplest most easily read, C statements that can be found to express it.

Each line of code we put in the kernel will be read by many people doing various things. They will be more likely to have a correct understanding of our code if it is clear and simple, with a minimum of surprises.

Yes, I agree. But sorry, honestly I didn't see any big cleanup in your patch. It's still using s/v/i... it is same readability at least for me...

Signature · 1 line
OGAWA Hirofumi <[email protected]>
#16 lore raw
Quoted 1 line

I didn't see any big cleanup in your patch.

That could well be <grin>. Beauty is in the eye of the beholder.

I figured that replacing the #define's with local variables was worth a couple of style points, and that explicitly checking that the user provided values were within limits, all the time, no ifdefs, was more straight forward.

But it is difficult to establish such preferences with certainty.

Again, thanks for considering my reply.

Do as you think best. I am afraid I have no more wisdom (if ever I had any ...).

Signature · 3 lines
                          I won't rest till it's the best ...
                          Programmer, Linux Scalability
                          Paul Jackson <[email protected]> 1.650.933.1373
#17 lore raw

Hate to be a bore, but I'm still waiting for a definitive patch ;)

#18 lore raw

Andrew:

Quoted 1 line

... still waiting ...

Don't wait on me ... as indicated in my last post on this lkml thread, I left this back in the hands of the expert, OGAWA Hirofumi.

Signature · 3 lines
                          I won't rest till it's the best ...
                          Programmer, Linux Scalability
                          Paul Jackson <[email protected]> 1.650.933.1373
#19 lore raw
Quoted 2 lines · Paul Jackson

Don't wait on me ... as indicated in my last post on this lkml thread, I left this back in the hands of the expert, OGAWA Hirofumi.

Could you please post your lastest patch? It seems that my patch does not satisfy peoples.

Signature · 1 line
OGAWA Hirofumi <[email protected]>
#20 lore raw
Quoted 1 line · Andrew

Hate to be a bore, but I'm still waiting for a definitive patch ;)

Quoted 2 lines · OGAWA Hirofumi

Could you please post your lastest patch? It seems that my patch does not satisfy peoples.

Hmmm ...

As is often the case, Andrew knows more than he lets on.

OGAWA,

I cannot post a latest patch. I do not know enough to do so.

I attempted some code readability comments, but probably I should not have, since I don't have the knowledge of this code that I should have in order to test it, nor to know by reading it what works.

You replied, a couple of messages ago, with entirely sensible comments to my posting. Since then, I have been doing my best to remove myself from this thread.

Unless you have something else you wish to propose, please tell Andrew to go with your patch, which (just to avoid confusion) I copy again below.

Your patch satisfies me just fine now.

Please let Andrew know if he should take it.

My apologies for making a confusion of this.

Thank-you for your good work and your patience.

[PATCH] Fix NR_KEYS off-by-one error

KDGKBENT ioctl can use 256 entries (0-255), but it was defined as key_map[NR_KEYS] (NR_KEYS == 255). The code seems also thinking it's 256.

	key_map[0] = U(K_ALLOCATED);
	for (j = 1; j < NR_KEYS; j++)
		key_map[j] = U(K_HOLE);

---

 drivers/char/vt_ioctl.c  |    6 ++++++
 include/linux/keyboard.h |    2 +-
 2 files changed, 7 insertions(+), 1 deletion(-)
include/linux/keyboard.h renamed from include/linux/keyboard.h~nr_keys-off-by-one +1 -1
diff -puN include/linux/keyboard.h~nr_keys-off-by-one include/linux/keyboard.h
@@ -16,7 +16,7 @@
 
 #define NR_SHIFT	9
 
-#define NR_KEYS		255
+#define NR_KEYS		256
 #define MAX_NR_KEYMAPS	256
 /* This means 128Kb if all keymaps are allocated. Only the superuser
 	may increase the number of keymaps beyond MAX_NR_OF_USER_KEYMAPS. */
drivers/char/vt_ioctl.c renamed from drivers/char/vt_ioctl.c~nr_keys-off-by-one +6 -0
diff -puN drivers/char/vt_ioctl.c~nr_keys-off-by-one drivers/char/vt_ioctl.c
@@ -83,6 +83,12 @@ do_kdsk_ioctl(int cmd, struct kbentry __
 	if (copy_from_user(&tmp, user_kbe, sizeof(struct kbentry)))
 		return -EFAULT;
 
+#if NR_KEYS != 256 || MAX_NR_KEYMAPS != 256
+#error "you should check this too"
+	if (i >= NR_KEYS || s >= MAX_NR_KEYMAPS)
+		return -EINVAL;
+#endif
+
 	switch (cmd) {
 	case KDGKBENT:
 		key_map = key_maps[s];

_
-

Signature · 3 lines
                          I won't rest till it's the best ...
                          Programmer, Linux Scalability
                          Paul Jackson <[email protected]> 1.650.933.1373
#21 lore raw

Hi!

Let me summarize.

In the past, the kernel had various different values of NR_KEYS, in this
order: 128, 512, 256, 255.

128 was not enough, 512 didn't fit in a byte (while allowed to address all keycodes the input layer uses), 256 broke some apps that relied on unsigned char counters, and thus we ended up with the maximum value that kept all software happy.

Now somewhere in the process (I assume in the 512 stage, but could be the 256 stage as well), the kernel produced warnings about impossible comparisons.

Thus the comparison(s) were dropped, by Andrew.

Then we finalized on 255, and the comparison is needed again to prevent overflowing the keymap arrays.

BUT some binaries are still compiled with 256 and try to set up a mapping for keycode 255 (although there is _no_ such keycode), and break. IMO it's a bug in the app.

Now I believe that simply adding the check back by reverting the old Andrew's patch and recompiling/fixing what breaks is the right way to go.

Any comments?

Signature · 2 lines
Vojtech Pavlik
SuSE Labs, SuSE CR
#22 lore raw
Quoted 8 lines · Vojtech Pavlik

Let me summarize.

In the past, the kernel had various different values of NR_KEYS, in this
order: 128, 512, 256, 255.

128 was not enough, 512 didn't fit in a byte (while allowed to address all keycodes the input layer uses), 256 broke some apps that relied on unsigned char counters,

Can you elaborate on this part? Which applications broke?

Quoted 8 lines

...
BUT some binaries are still compiled with 256 and try to set up a mapping for keycode 255 (although there is _no_ such keycode), and break. IMO it's a bug in the app.

Now I believe that simply adding the check back by reverting the old Andrew's patch and recompiling/fixing what breaks is the right way to go.

Revert Andrew's patch: yes.
Choosing 255/256 - I have no opinion yet, my opinion will depend on your answer to the above "Which applications broke?".

Andries

#23 lore raw
Quoted 10 lines · Andries Brouwer
Quoted 8 lines

Let me summarize.

In the past, the kernel had various different values of NR_KEYS, in this
order: 128, 512, 256, 255.

128 was not enough, 512 didn't fit in a byte (while allowed to address all keycodes the input layer uses), 256 broke some apps that relied on unsigned char counters,

Can you elaborate on this part? Which applications broke?

Unfortunately I don't remember. I'll dig my mailbox to see if I can find anything.

Quoted 11 lines
Quoted 7 lines

BUT some binaries are still compiled with 256 and try to set up a mapping for keycode 255 (although there is _no_ such keycode), and break. IMO it's a bug in the app.

Now I believe that simply adding the check back by reverting the old Andrew's patch and recompiling/fixing what breaks is the right way to go.

Revert Andrew's patch: yes.
Choosing 255/256 - I have no opinion yet, my opinion will depend on your answer to the above "Which applications broke?".

Signature · 2 lines
Vojtech Pavlik
SuSE Labs, SuSE CR
#24 lore raw
In reply to Andries Brouwer
Quoted 4 lines · Andries Brouwer
Quoted 2 lines · Vojtech Pavlik

Let me summarize.

Quoted 8 lines
Quoted 6 lines

In the past, the kernel had various different values of NR_KEYS, in this
order: 128, 512, 256, 255.

128 was not enough, 512 didn't fit in a byte (while allowed to address all keycodes the input layer uses), 256 broke some apps that relied on unsigned char counters,

Can you elaborate on this part? Which applications broke?

Hmm, so bk says it was the other way around:

128, 256, 512, 255

And 256 probably worked for most people, except loadkeys had to be changed not to #define NR_KEYS itself. So now I believe that 256 could actually be safe.

Quoted 3 lines

Revert Andrew's patch: yes.
Choosing 255/256 - I have no opinion yet, my opinion will depend on your answer to the above "Which applications broke?".

Signature · 2 lines
Vojtech Pavlik
SuSE Labs, SuSE CR