linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / drivers / s390 / char / keyboard.c
index b124ebb..a317a12 100644 (file)
@@ -32,11 +32,11 @@ static k_handler_fn K_HANDLERS;
 static k_handler_fn *k_handler[16] = { K_HANDLERS };
 
 /* maximum values each key_handler can handle */
-static const int max_vals[] = {
+static const int kbd_max_vals[] = {
        255, ARRAY_SIZE(func_table) - 1, NR_FN_HANDLER - 1, 0,
        NR_DEAD - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0
 };
-static const int NR_TYPES = ARRAY_SIZE(max_vals);
+static const int KBD_NR_TYPES = ARRAY_SIZE(kbd_max_vals);
 
 static unsigned char ret_diacr[NR_DEAD] = {
        '`', '\'', '^', '~', '"', ','
@@ -99,13 +99,11 @@ out_fn_handler:
        kfree(kbd->fn_handler);
 out_func:
        for (i = 0; i < ARRAY_SIZE(func_table); i++)
-               if (kbd->func_table[i])
-                       kfree(kbd->func_table[i]);
+               kfree(kbd->func_table[i]);
        kfree(kbd->func_table);
 out_maps:
        for (i = 0; i < ARRAY_SIZE(key_maps); i++)
-               if (kbd->key_maps[i])
-                       kfree(kbd->key_maps[i]);
+               kfree(kbd->key_maps[i]);
        kfree(kbd->key_maps);
 out_kbd:
        kfree(kbd);
@@ -121,12 +119,10 @@ kbd_free(struct kbd_data *kbd)
        kfree(kbd->accent_table);
        kfree(kbd->fn_handler);
        for (i = 0; i < ARRAY_SIZE(func_table); i++)
-               if (kbd->func_table[i])
-                       kfree(kbd->func_table[i]);
+               kfree(kbd->func_table[i]);
        kfree(kbd->func_table);
        for (i = 0; i < ARRAY_SIZE(key_maps); i++)
-               if (kbd->key_maps[i])
-                       kfree(kbd->key_maps[i]);
+               kfree(kbd->key_maps[i]);
        kfree(kbd->key_maps);
        kfree(kbd);
 }
@@ -338,7 +334,7 @@ kbd_keycode(struct kbd_data *kbd, unsigned int keycode)
  * Ioctl stuff.
  */
 static int
-do_kdsk_ioctl(struct kbd_data *kbd, struct kbentry *user_kbe,
+do_kdsk_ioctl(struct kbd_data *kbd, struct kbentry __user *user_kbe,
              int cmd, int perm)
 {
        struct kbentry tmp;
@@ -360,7 +356,7 @@ do_kdsk_ioctl(struct kbd_data *kbd, struct kbentry *user_kbe,
                key_map = kbd->key_maps[tmp.kb_table];
                if (key_map) {
                    val = U(key_map[tmp.kb_index]);
-                   if (KTYP(val) >= NR_TYPES)
+                   if (KTYP(val) >= KBD_NR_TYPES)
                        val = K_HOLE;
                } else
                    val = (tmp.kb_index ? K_HOLE : K_NOSUCHMAP);
@@ -378,9 +374,9 @@ do_kdsk_ioctl(struct kbd_data *kbd, struct kbentry *user_kbe,
                        break;
                }
 
-               if (KTYP(tmp.kb_value) >= NR_TYPES)
+               if (KTYP(tmp.kb_value) >= KBD_NR_TYPES)
                        return -EINVAL;
-               if (KVAL(tmp.kb_value) > max_vals[KTYP(tmp.kb_value)])
+               if (KVAL(tmp.kb_value) > kbd_max_vals[KTYP(tmp.kb_value)])
                        return -EINVAL;
 
                if (!(key_map = kbd->key_maps[tmp.kb_table])) {
@@ -410,7 +406,7 @@ do_kdsk_ioctl(struct kbd_data *kbd, struct kbentry *user_kbe,
 }
 
 static int
-do_kdgkb_ioctl(struct kbd_data *kbd, struct kbsentry *u_kbs,
+do_kdgkb_ioctl(struct kbd_data *kbd, struct kbsentry __user *u_kbs,
               int cmd, int perm)
 {
        unsigned char kb_func;
@@ -444,7 +440,11 @@ do_kdgkb_ioctl(struct kbd_data *kbd, struct kbsentry *u_kbs,
                        return -EPERM;
                len = strnlen_user(u_kbs->kb_string,
                                   sizeof(u_kbs->kb_string) - 1);
-               p = kmalloc(len, GFP_KERNEL);
+               if (!len)
+                       return -EFAULT;
+               if (len > sizeof(u_kbs->kb_string) - 1)
+                       return -EINVAL;
+               p = kmalloc(len + 1, GFP_KERNEL);
                if (!p)
                        return -ENOMEM;
                if (copy_from_user(p, u_kbs->kb_string, len)) {
@@ -452,8 +452,7 @@ do_kdgkb_ioctl(struct kbd_data *kbd, struct kbsentry *u_kbs,
                        return -EFAULT;
                }
                p[len] = 0;
-               if (kbd->func_table[kb_func])
-                       kfree(kbd->func_table[kb_func]);
+               kfree(kbd->func_table[kb_func]);
                kbd->func_table[kb_func] = p;
                break;
        }
@@ -464,9 +463,12 @@ int
 kbd_ioctl(struct kbd_data *kbd, struct file *file,
          unsigned int cmd, unsigned long arg)
 {
-       struct kbdiacrs *a;
+       struct kbdiacrs __user *a;
+       void __user *argp;
        int ct, perm;
 
+       argp = (void __user *)arg;
+
        /*
         * To have permissions to do most of the vt ioctls, we either have
         * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG.
@@ -474,15 +476,15 @@ kbd_ioctl(struct kbd_data *kbd, struct file *file,
        perm = current->signal->tty == kbd->tty || capable(CAP_SYS_TTY_CONFIG);
        switch (cmd) {
        case KDGKBTYPE:
-               return put_user(KB_101, (char*) arg);
+               return put_user(KB_101, (char __user *)argp);
        case KDGKBENT:
        case KDSKBENT:
-               return do_kdsk_ioctl(kbd, (struct kbentry *)arg, cmd, perm);
+               return do_kdsk_ioctl(kbd, argp, cmd, perm);
        case KDGKBSENT:
        case KDSKBSENT:
-               return do_kdgkb_ioctl(kbd, (struct kbsentry *)arg, cmd, perm);
+               return do_kdgkb_ioctl(kbd, argp, cmd, perm);
        case KDGKBDIACR:
-               a = (struct kbdiacrs *) arg;
+               a = argp;
 
                if (put_user(kbd->accent_table_size, &a->kb_cnt))
                        return -EFAULT;
@@ -492,7 +494,7 @@ kbd_ioctl(struct kbd_data *kbd, struct file *file,
                        return -EFAULT;
                return 0;
        case KDSKBDIACR:
-               a = (struct kbdiacrs *) arg;
+               a = argp;
                if (!perm)
                        return -EPERM;
                if (get_user(ct, &a->kb_cnt))