Commit cb995148 authored by Andrew Morton's avatar Andrew Morton Committed by Dave Jones

[PATCH] stack reduction in drivers/char/vt_ioctl.c

Patch from "Randy.Dunlap" <randy.dunlap@verizon.net>

This patch (to 2.5.64) reduces the stack usage in vt_ioctl()
from 0x334 bytes to 0xec bytes (P4, UP, gcc 2.96).
parent 8e82373a
...@@ -191,38 +191,56 @@ do_kbkeycode_ioctl(int cmd, struct kbkeycode *user_kbkc, int perm) ...@@ -191,38 +191,56 @@ do_kbkeycode_ioctl(int cmd, struct kbkeycode *user_kbkc, int perm)
static inline int static inline int
do_kdgkb_ioctl(int cmd, struct kbsentry *user_kdgkb, int perm) do_kdgkb_ioctl(int cmd, struct kbsentry *user_kdgkb, int perm)
{ {
struct kbsentry tmp; struct kbsentry *kbs;
char *p; char *p;
u_char *q; u_char *q;
int sz; int sz;
int delta; int delta;
char *first_free, *fj, *fnw; char *first_free, *fj, *fnw;
int i, j, k; int i, j, k;
int ret;
kbs = kmalloc(sizeof(*kbs), GFP_KERNEL);
if (!kbs) {
ret = -ENOMEM;
goto reterr;
}
/* we mostly copy too much here (512bytes), but who cares ;) */ /* we mostly copy too much here (512bytes), but who cares ;) */
if (copy_from_user(&tmp, user_kdgkb, sizeof(struct kbsentry))) if (copy_from_user(kbs, user_kdgkb, sizeof(struct kbsentry))) {
return -EFAULT; ret = -EFAULT;
tmp.kb_string[sizeof(tmp.kb_string)-1] = '\0'; goto reterr;
if (tmp.kb_func >= MAX_NR_FUNC) }
return -EINVAL; kbs->kb_string[sizeof(kbs->kb_string)-1] = '\0';
i = tmp.kb_func; if (kbs->kb_func >= MAX_NR_FUNC) {
ret = -EINVAL;
goto reterr;
}
i = kbs->kb_func;
switch (cmd) { switch (cmd) {
case KDGKBSENT: case KDGKBSENT:
sz = sizeof(tmp.kb_string) - 1; /* sz should have been sz = sizeof(kbs->kb_string) - 1; /* sz should have been
a struct member */ a struct member */
q = user_kdgkb->kb_string; q = user_kdgkb->kb_string;
p = func_table[i]; p = func_table[i];
if(p) if(p)
for ( ; *p && sz; p++, sz--) for ( ; *p && sz; p++, sz--)
if (put_user(*p, q++)) if (put_user(*p, q++)) {
return -EFAULT; ret = -EFAULT;
if (put_user('\0', q)) goto reterr;
return -EFAULT; }
if (put_user('\0', q)) {
ret = -EFAULT;
goto reterr;
}
kfree(kbs);
return ((p && *p) ? -EOVERFLOW : 0); return ((p && *p) ? -EOVERFLOW : 0);
case KDSKBSENT: case KDSKBSENT:
if (!perm) if (!perm) {
return -EPERM; ret = -EPERM;
goto reterr;
}
q = func_table[i]; q = func_table[i];
first_free = funcbufptr + (funcbufsize - funcbufleft); first_free = funcbufptr + (funcbufsize - funcbufleft);
...@@ -233,7 +251,7 @@ do_kdgkb_ioctl(int cmd, struct kbsentry *user_kdgkb, int perm) ...@@ -233,7 +251,7 @@ do_kdgkb_ioctl(int cmd, struct kbsentry *user_kdgkb, int perm)
else else
fj = first_free; fj = first_free;
delta = (q ? -strlen(q) : 1) + strlen(tmp.kb_string); delta = (q ? -strlen(q) : 1) + strlen(kbs->kb_string);
if (delta <= funcbufleft) { /* it fits in current buf */ if (delta <= funcbufleft) { /* it fits in current buf */
if (j < MAX_NR_FUNC) { if (j < MAX_NR_FUNC) {
memmove(fj + delta, fj, first_free - fj); memmove(fj + delta, fj, first_free - fj);
...@@ -249,8 +267,10 @@ do_kdgkb_ioctl(int cmd, struct kbsentry *user_kdgkb, int perm) ...@@ -249,8 +267,10 @@ do_kdgkb_ioctl(int cmd, struct kbsentry *user_kdgkb, int perm)
while (sz < funcbufsize - funcbufleft + delta) while (sz < funcbufsize - funcbufleft + delta)
sz <<= 1; sz <<= 1;
fnw = (char *) kmalloc(sz, GFP_KERNEL); fnw = (char *) kmalloc(sz, GFP_KERNEL);
if(!fnw) if(!fnw) {
return -ENOMEM; ret = -ENOMEM;
goto reterr;
}
if (!q) if (!q)
func_table[i] = fj; func_table[i] = fj;
...@@ -272,17 +292,19 @@ do_kdgkb_ioctl(int cmd, struct kbsentry *user_kdgkb, int perm) ...@@ -272,17 +292,19 @@ do_kdgkb_ioctl(int cmd, struct kbsentry *user_kdgkb, int perm)
funcbufleft = funcbufleft - delta + sz - funcbufsize; funcbufleft = funcbufleft - delta + sz - funcbufsize;
funcbufsize = sz; funcbufsize = sz;
} }
strcpy(func_table[i], tmp.kb_string); strcpy(func_table[i], kbs->kb_string);
break; break;
} }
return 0; ret = 0;
reterr:
kfree(kbs);
return ret;
} }
static inline int static inline int
do_fontx_ioctl(int cmd, struct consolefontdesc *user_cfd, int perm) do_fontx_ioctl(int cmd, struct consolefontdesc *user_cfd, int perm, struct console_font_op *op)
{ {
struct consolefontdesc cfdarg; struct consolefontdesc cfdarg;
struct console_font_op op;
int i; int i;
if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc))) if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc)))
...@@ -292,25 +314,25 @@ do_fontx_ioctl(int cmd, struct consolefontdesc *user_cfd, int perm) ...@@ -292,25 +314,25 @@ do_fontx_ioctl(int cmd, struct consolefontdesc *user_cfd, int perm)
case PIO_FONTX: case PIO_FONTX:
if (!perm) if (!perm)
return -EPERM; return -EPERM;
op.op = KD_FONT_OP_SET; op->op = KD_FONT_OP_SET;
op.flags = KD_FONT_FLAG_OLD; op->flags = KD_FONT_FLAG_OLD;
op.width = 8; op->width = 8;
op.height = cfdarg.charheight; op->height = cfdarg.charheight;
op.charcount = cfdarg.charcount; op->charcount = cfdarg.charcount;
op.data = cfdarg.chardata; op->data = cfdarg.chardata;
return con_font_op(fg_console, &op); return con_font_op(fg_console, op);
case GIO_FONTX: { case GIO_FONTX: {
op.op = KD_FONT_OP_GET; op->op = KD_FONT_OP_GET;
op.flags = KD_FONT_FLAG_OLD; op->flags = KD_FONT_FLAG_OLD;
op.width = 8; op->width = 8;
op.height = cfdarg.charheight; op->height = cfdarg.charheight;
op.charcount = cfdarg.charcount; op->charcount = cfdarg.charcount;
op.data = cfdarg.chardata; op->data = cfdarg.chardata;
i = con_font_op(fg_console, &op); i = con_font_op(fg_console, op);
if (i) if (i)
return i; return i;
cfdarg.charheight = op.height; cfdarg.charheight = op->height;
cfdarg.charcount = op.charcount; cfdarg.charcount = op->charcount;
if (copy_to_user(user_cfd, &cfdarg, sizeof(struct consolefontdesc))) if (copy_to_user(user_cfd, &cfdarg, sizeof(struct consolefontdesc)))
return -EFAULT; return -EFAULT;
return 0; return 0;
...@@ -355,6 +377,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, ...@@ -355,6 +377,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
unsigned char ucval; unsigned char ucval;
struct kbd_struct * kbd; struct kbd_struct * kbd;
struct vt_struct *vt = (struct vt_struct *)tty->driver_data; struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
struct console_font_op op; /* used in multiple places here */
console = vt->vc_num; console = vt->vc_num;
...@@ -860,7 +883,6 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, ...@@ -860,7 +883,6 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
} }
case PIO_FONT: { case PIO_FONT: {
struct console_font_op op;
if (!perm) if (!perm)
return -EPERM; return -EPERM;
op.op = KD_FONT_OP_SET; op.op = KD_FONT_OP_SET;
...@@ -873,7 +895,6 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, ...@@ -873,7 +895,6 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
} }
case GIO_FONT: { case GIO_FONT: {
struct console_font_op op;
op.op = KD_FONT_OP_GET; op.op = KD_FONT_OP_GET;
op.flags = KD_FONT_FLAG_OLD; op.flags = KD_FONT_FLAG_OLD;
op.width = 8; op.width = 8;
...@@ -893,7 +914,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, ...@@ -893,7 +914,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
case PIO_FONTX: case PIO_FONTX:
case GIO_FONTX: case GIO_FONTX:
return do_fontx_ioctl(cmd, (struct consolefontdesc *)arg, perm); return do_fontx_ioctl(cmd, (struct consolefontdesc *)arg, perm, &op);
case PIO_FONTRESET: case PIO_FONTRESET:
{ {
...@@ -906,7 +927,6 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, ...@@ -906,7 +927,6 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
return -ENOSYS; return -ENOSYS;
#else #else
{ {
struct console_font_op op;
op.op = KD_FONT_OP_SET_DEFAULT; op.op = KD_FONT_OP_SET_DEFAULT;
op.data = NULL; op.data = NULL;
i = con_font_op(fg_console, &op); i = con_font_op(fg_console, &op);
...@@ -918,7 +938,6 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, ...@@ -918,7 +938,6 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
} }
case KDFONTOP: { case KDFONTOP: {
struct console_font_op op;
if (copy_from_user(&op, (void *) arg, sizeof(op))) if (copy_from_user(&op, (void *) arg, sizeof(op)))
return -EFAULT; return -EFAULT;
if (!perm && op.op != KD_FONT_OP_GET) if (!perm && op.op != KD_FONT_OP_GET)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment