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

Randy.Dunlap (randy.dunlap@verizon.net)
Sun, 09 Mar 2003 22:26:36 -0800


This is a multi-part message in MIME format.
--------------90626E56CD14A9127835B47F
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Hi,

This patch (to 2.5.64) reduces the stack usage in vt_ioctl()
from 0x334 bytes to 0xec bytes (P4, UP, gcc 2.96).

Any problems, comments?
If not, please apply.

Thanks,
~Randy
--------------90626E56CD14A9127835B47F
Content-Type: text/plain; charset=us-ascii;
name="vt_ioctl_stack.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="vt_ioctl_stack.patch"

patch_name: vt_ioctl_stack.patch
patch_version: 2003-03-09.22:16:16
author: Randy.Dunlap <rddunlap@osdl.org>
description: reduces stack usage in drivers/char/vt_ioctl.c::vt_ioctl() from
0x334 bytes to 0xec bytes (P4, UP, gcc 2.96)
product: Linux
product_versions: linux-2564
changelog: _
URL: _
requires: _
conflicts: _
maintainer: jsimmons@users.sf.net, jsimmons@infradead.org
diffstat: =
drivers/char/vt_ioctl.c | 103 ++++++++++++++++++++++++++++--------------------
1 files changed, 62 insertions(+), 41 deletions(-)

diff -Naur ./drivers/char/vt_ioctl.c%VTSTK ./drivers/char/vt_ioctl.c
--- ./drivers/char/vt_ioctl.c%VTSTK Tue Mar 4 19:29:31 2003
+++ ./drivers/char/vt_ioctl.c Sun Mar 9 21:59:39 2003
@@ -191,38 +191,56 @@
static inline int
do_kdgkb_ioctl(int cmd, struct kbsentry *user_kdgkb, int perm)
{
- struct kbsentry tmp;
+ struct kbsentry *kbs;
char *p;
u_char *q;
int sz;
int delta;
char *first_free, *fj, *fnw;
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 ;) */
- if (copy_from_user(&tmp, user_kdgkb, sizeof(struct kbsentry)))
- return -EFAULT;
- tmp.kb_string[sizeof(tmp.kb_string)-1] = '\0';
- if (tmp.kb_func >= MAX_NR_FUNC)
- return -EINVAL;
- i = tmp.kb_func;
+ if (copy_from_user(kbs, user_kdgkb, sizeof(struct kbsentry))) {
+ ret = -EFAULT;
+ goto reterr;
+ }
+ kbs->kb_string[sizeof(kbs->kb_string)-1] = '\0';
+ if (kbs->kb_func >= MAX_NR_FUNC) {
+ ret = -EINVAL;
+ goto reterr;
+ }
+ i = kbs->kb_func;

switch (cmd) {
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 */
q = user_kdgkb->kb_string;
p = func_table[i];
if(p)
for ( ; *p && sz; p++, sz--)
- if (put_user(*p, q++))
- return -EFAULT;
- if (put_user('\0', q))
- return -EFAULT;
+ if (put_user(*p, q++)) {
+ ret = -EFAULT;
+ goto reterr;
+ }
+ if (put_user('\0', q)) {
+ ret = -EFAULT;
+ goto reterr;
+ }
+ kfree(kbs);
return ((p && *p) ? -EOVERFLOW : 0);
case KDSKBSENT:
- if (!perm)
- return -EPERM;
+ if (!perm) {
+ ret = -EPERM;
+ goto reterr;
+ }

q = func_table[i];
first_free = funcbufptr + (funcbufsize - funcbufleft);
@@ -233,7 +251,7 @@
else
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 (j < MAX_NR_FUNC) {
memmove(fj + delta, fj, first_free - fj);
@@ -249,8 +267,10 @@
while (sz < funcbufsize - funcbufleft + delta)
sz <<= 1;
fnw = (char *) kmalloc(sz, GFP_KERNEL);
- if(!fnw)
- return -ENOMEM;
+ if(!fnw) {
+ ret = -ENOMEM;
+ goto reterr;
+ }

if (!q)
func_table[i] = fj;
@@ -272,17 +292,21 @@
funcbufleft = funcbufleft - delta + sz - funcbufsize;
funcbufsize = sz;
}
- strcpy(func_table[i], tmp.kb_string);
+ strcpy(func_table[i], kbs->kb_string);
break;
}
+ kfree(kbs);
return 0;
+
+reterr:
+ kfree(kbs);
+ return ret;
}

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 console_font_op op;
int i;

if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc)))
@@ -292,25 +316,25 @@
case PIO_FONTX:
if (!perm)
return -EPERM;
- op.op = KD_FONT_OP_SET;
- op.flags = KD_FONT_FLAG_OLD;
- op.width = 8;
- op.height = cfdarg.charheight;
- op.charcount = cfdarg.charcount;
- op.data = cfdarg.chardata;
- return con_font_op(fg_console, &op);
+ op->op = KD_FONT_OP_SET;
+ op->flags = KD_FONT_FLAG_OLD;
+ op->width = 8;
+ op->height = cfdarg.charheight;
+ op->charcount = cfdarg.charcount;
+ op->data = cfdarg.chardata;
+ return con_font_op(fg_console, op);
case GIO_FONTX: {
- op.op = KD_FONT_OP_GET;
- op.flags = KD_FONT_FLAG_OLD;
- op.width = 8;
- op.height = cfdarg.charheight;
- op.charcount = cfdarg.charcount;
- op.data = cfdarg.chardata;
- i = con_font_op(fg_console, &op);
+ op->op = KD_FONT_OP_GET;
+ op->flags = KD_FONT_FLAG_OLD;
+ op->width = 8;
+ op->height = cfdarg.charheight;
+ op->charcount = cfdarg.charcount;
+ op->data = cfdarg.chardata;
+ i = con_font_op(fg_console, op);
if (i)
return i;
- cfdarg.charheight = op.height;
- cfdarg.charcount = op.charcount;
+ cfdarg.charheight = op->height;
+ cfdarg.charcount = op->charcount;
if (copy_to_user(user_cfd, &cfdarg, sizeof(struct consolefontdesc)))
return -EFAULT;
return 0;
@@ -355,6 +379,7 @@
unsigned char ucval;
struct kbd_struct * kbd;
struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
+ struct console_font_op op; /* used in multiple places here */

console = vt->vc_num;

@@ -860,7 +885,6 @@
}

case PIO_FONT: {
- struct console_font_op op;
if (!perm)
return -EPERM;
op.op = KD_FONT_OP_SET;
@@ -873,7 +897,6 @@
}

case GIO_FONT: {
- struct console_font_op op;
op.op = KD_FONT_OP_GET;
op.flags = KD_FONT_FLAG_OLD;
op.width = 8;
@@ -893,7 +916,7 @@

case PIO_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:
{
@@ -906,7 +929,6 @@
return -ENOSYS;
#else
{
- struct console_font_op op;
op.op = KD_FONT_OP_SET_DEFAULT;
op.data = NULL;
i = con_font_op(fg_console, &op);
@@ -918,7 +940,6 @@
}

case KDFONTOP: {
- struct console_font_op op;
if (copy_from_user(&op, (void *) arg, sizeof(op)))
return -EFAULT;
if (!perm && op.op != KD_FONT_OP_GET)

--------------90626E56CD14A9127835B47F--

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/