[PATCH 08/25] tty: move ioctl32 code over to vt_ioctl.c and tty_io.c

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch introduces line discipline specific and tty device specific
compat_ioctl callbacks as well as moving over all generic tty ioctl
and vt ioctl conversion handlers over to the local files that are
already responsible for the native ioctls.

Signed-off-by: Arnd Bergmann <[email protected]>

Index: linux-2.6.14-rc/drivers/char/vt.c
===================================================================
--- linux-2.6.14-rc.orig/drivers/char/vt.c	2005-11-05 02:41:10.000000000 +0100
+++ linux-2.6.14-rc/drivers/char/vt.c	2005-11-05 02:41:32.000000000 +0100
@@ -2614,6 +2614,9 @@
 	.flush_chars = con_flush_chars,
 	.chars_in_buffer = con_chars_in_buffer,
 	.ioctl = vt_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = vt_compat_ioctl,
+#endif
 	.stop = con_stop,
 	.start = con_start,
 	.throttle = con_throttle,
Index: linux-2.6.14-rc/drivers/char/vt_ioctl.c
===================================================================
--- linux-2.6.14-rc.orig/drivers/char/vt_ioctl.c	2005-11-05 02:41:10.000000000 +0100
+++ linux-2.6.14-rc/drivers/char/vt_ioctl.c	2005-11-05 02:41:32.000000000 +0100
@@ -26,6 +26,7 @@
 #include <linux/console.h>
 #include <linux/signal.h>
 #include <linux/timex.h>
+#include <linux/compat.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -1201,3 +1202,197 @@
 
 	complete_change_console(new_vc);
 }
+
+#ifdef CONFIG_COMPAT
+
+static int vt_check(struct file *file, struct tty_struct *tty)
+{
+	struct inode *inode = file->f_dentry->d_inode;
+
+	if (tty_paranoia_check(tty, inode, "tty_ioctl"))
+		return -EINVAL;
+	/*
+	 * To have permissions to do most of the vt ioctls, we either have
+	 * to be the owner of the tty, or super-user.
+	 */
+	if (current->signal->tty == tty || capable(CAP_SYS_ADMIN))
+		return 1;
+	return 0;
+}
+
+struct consolefontdesc32 {
+	unsigned short charcount;       /* characters in font (256 or 512) */
+	unsigned short charheight;      /* scan lines per character (1-32) */
+	compat_caddr_t chardata;	/* font data in expanded form */
+};
+
+static int compat_fontx_ioctl(struct tty_struct *tty, struct file *file,
+				unsigned int cmd, unsigned long arg)
+{
+	struct consolefontdesc32 __user *user_cfd = compat_ptr(arg);
+	struct console_font_op op;
+	compat_caddr_t data;
+	int i, perm;
+
+	perm = vt_check(file, tty);
+	if (perm < 0) return perm;
+
+	switch (cmd) {
+	case PIO_FONTX:
+		if (!perm)
+			return -EPERM;
+		op.op = KD_FONT_OP_SET;
+		op.flags = 0;
+		op.width = 8;
+		if (get_user(op.height, &user_cfd->charheight) ||
+		    get_user(op.charcount, &user_cfd->charcount) ||
+		    get_user(data, &user_cfd->chardata))
+			return -EFAULT;
+		op.data = compat_ptr(data);
+		return con_font_op(vc_cons[fg_console].d, &op);
+	case GIO_FONTX:
+		op.op = KD_FONT_OP_GET;
+		op.flags = 0;
+		op.width = 8;
+		if (get_user(op.height, &user_cfd->charheight) ||
+		    get_user(op.charcount, &user_cfd->charcount) ||
+		    get_user(data, &user_cfd->chardata))
+			return -EFAULT;
+		if (!data)
+			return 0;
+		op.data = compat_ptr(data);
+		i = con_font_op(vc_cons[fg_console].d, &op);
+		if (i)
+			return i;
+		if (put_user(op.height, &user_cfd->charheight) ||
+		    put_user(op.charcount, &user_cfd->charcount) ||
+		    put_user((compat_caddr_t)(unsigned long)op.data,
+				&user_cfd->chardata))
+			return -EFAULT;
+		return 0;
+	}
+	return -EINVAL;
+}
+
+struct console_font_op32 {
+	compat_uint_t op;        /* operation code KD_FONT_OP_* */
+	compat_uint_t flags;     /* KD_FONT_FLAG_* */
+	compat_uint_t width, height;     /* font size */
+	compat_uint_t charcount;
+	compat_caddr_t data;    /* font data with height fixed to 32 */
+};
+
+static int compat_kdfontop_ioctl(struct tty_struct *tty, struct file *file,
+				unsigned int cmd, unsigned long arg)
+{
+	struct console_font_op op;
+	struct console_font_op32 __user *fontop = compat_ptr(arg);
+	int perm = vt_check(file, tty), i;
+	struct vc_data *vc;
+
+	if (perm < 0) return perm;
+
+	if (copy_from_user(&op, fontop, sizeof(struct console_font_op32)))
+		return -EFAULT;
+	if (!perm && op.op != KD_FONT_OP_GET)
+		return -EPERM;
+	op.data = compat_ptr(((struct console_font_op32 *)&op)->data);
+	op.flags |= KD_FONT_FLAG_OLD;
+	vc = ((struct tty_struct *)file->private_data)->driver_data;
+	i = con_font_op(vc, &op);
+	if (i)
+		return i;
+	((struct console_font_op32 *)&op)->data = (unsigned long)op.data;
+	if (copy_to_user(fontop, &op, sizeof(struct console_font_op32)))
+		return -EFAULT;
+	return 0;
+}
+
+struct unimapdesc32 {
+	unsigned short entry_ct;
+	compat_caddr_t entries;
+};
+
+static int compat_unimap_ioctl(struct tty_struct *tty, struct file *file,
+				unsigned int cmd, unsigned long arg)
+{
+	struct unimapdesc32 tmp;
+	struct unimapdesc32 __user *user_ud = compat_ptr(arg);
+	int perm = vt_check(file, tty);
+
+	if (perm < 0) return perm;
+	if (copy_from_user(&tmp, user_ud, sizeof tmp))
+		return -EFAULT;
+	switch (cmd) {
+	case PIO_UNIMAP:
+		if (!perm) return -EPERM;
+		return con_set_unimap(vc_cons[fg_console].d, tmp.entry_ct, compat_ptr(tmp.entries));
+	case GIO_UNIMAP:
+		return con_get_unimap(vc_cons[fg_console].d, tmp.entry_ct, &(user_ud->entry_ct), compat_ptr(tmp.entries));
+	}
+	return 0;
+}
+
+int vt_compat_ioctl(struct tty_struct *tty, struct file * file,
+		    unsigned int cmd, unsigned long arg)
+{
+	int ret = -ENOIOCTLCMD;
+	lock_kernel();
+	switch (cmd) {
+	case PIO_FONTX:
+	case GIO_FONTX:
+		ret = compat_fontx_ioctl(tty, file, cmd, arg);
+		break;
+	case PIO_UNIMAP:
+	case GIO_UNIMAP:
+		ret = compat_unimap_ioctl(tty, file, cmd, arg);
+		break;
+	case KDFONTOP:
+		ret = compat_kdfontop_ioctl(tty, file, cmd, arg);
+		break;
+	case KDGETKEYCODE:
+	case KDGETLED:
+	case KDGETMODE:
+	case KDGKBLED:
+	case KDGKBMETA:
+	case KDGKBMODE:
+	case KDKBDREP:
+	case KDSETKEYCODE:
+	case PIO_FONT:
+	case PIO_FONTRESET:
+	case PIO_SCRNMAP:
+	case PIO_UNIMAPCLR:
+	case PIO_UNISCRNMAP:
+	case GIO_FONT:
+	case GIO_SCRNMAP:
+	case GIO_UNISCRNMAP:
+	case VT_SETMODE:
+	case VT_GETMODE:
+	case VT_GETSTATE:
+	case VT_OPENQRY:
+	case VT_RESIZE:
+	case VT_RESIZEX:
+	case VT_LOCKSWITCH:
+	case VT_UNLOCKSWITCH:
+		ret = vt_ioctl(tty, file, cmd,
+			(unsigned long)(compat_ptr(arg)));
+		break;
+	case KDMKTONE:
+	case KDSETLED:
+	case KDSETMODE:
+	case KDSIGACCEPT:
+	case KDSKBLED:
+	case KDSKBMETA:
+	case KDSKBMODE:
+	case KIOCSOUND:
+	case VT_ACTIVATE:
+	case VT_WAITACTIVE:
+	case VT_RELDISP:
+	case VT_DISALLOCATE:
+		ret = vt_ioctl(tty, file, cmd, arg);
+		break;
+	}
+	unlock_kernel();
+	return ret;
+}
+#endif
Index: linux-2.6.14-rc/fs/compat_ioctl.c
===================================================================
--- linux-2.6.14-rc.orig/fs/compat_ioctl.c	2005-11-05 02:41:31.000000000 +0100
+++ linux-2.6.14-rc/fs/compat_ioctl.c	2005-11-05 02:41:32.000000000 +0100
@@ -938,146 +938,6 @@
 	return err;
 }
 
-extern int tty_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg);
-
-#ifdef CONFIG_VT
-
-static int vt_check(struct file *file)
-{
-	struct tty_struct *tty;
-	struct inode *inode = file->f_dentry->d_inode;
-	
-	if (file->f_op->ioctl != tty_ioctl)
-		return -EINVAL;
-	                
-	tty = (struct tty_struct *)file->private_data;
-	if (tty_paranoia_check(tty, inode, "tty_ioctl"))
-		return -EINVAL;
-	                                                
-	if (tty->driver->ioctl != vt_ioctl)
-		return -EINVAL;
-	
-	/*
-	 * To have permissions to do most of the vt ioctls, we either have
-	 * to be the owner of the tty, or super-user.
-	 */
-	if (current->signal->tty == tty || capable(CAP_SYS_ADMIN))
-		return 1;
-	return 0;                                                    
-}
-
-struct consolefontdesc32 {
-	unsigned short charcount;       /* characters in font (256 or 512) */
-	unsigned short charheight;      /* scan lines per character (1-32) */
-	compat_caddr_t chardata;	/* font data in expanded form */
-};
-
-static int do_fontx_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file)
-{
-	struct consolefontdesc32 __user *user_cfd = compat_ptr(arg);
-	struct console_font_op op;
-	compat_caddr_t data;
-	int i, perm;
-
-	perm = vt_check(file);
-	if (perm < 0) return perm;
-	
-	switch (cmd) {
-	case PIO_FONTX:
-		if (!perm)
-			return -EPERM;
-		op.op = KD_FONT_OP_SET;
-		op.flags = 0;
-		op.width = 8;
-		if (get_user(op.height, &user_cfd->charheight) ||
-		    get_user(op.charcount, &user_cfd->charcount) ||
-		    get_user(data, &user_cfd->chardata))
-			return -EFAULT;
-		op.data = compat_ptr(data);
-		return con_font_op(vc_cons[fg_console].d, &op);
-	case GIO_FONTX:
-		op.op = KD_FONT_OP_GET;
-		op.flags = 0;
-		op.width = 8;
-		if (get_user(op.height, &user_cfd->charheight) ||
-		    get_user(op.charcount, &user_cfd->charcount) ||
-		    get_user(data, &user_cfd->chardata))
-			return -EFAULT;
-		if (!data)
-			return 0;
-		op.data = compat_ptr(data);
-		i = con_font_op(vc_cons[fg_console].d, &op);
-		if (i)
-			return i;
-		if (put_user(op.height, &user_cfd->charheight) ||
-		    put_user(op.charcount, &user_cfd->charcount) ||
-		    put_user((compat_caddr_t)(unsigned long)op.data,
-				&user_cfd->chardata))
-			return -EFAULT;
-		return 0;
-	}
-	return -EINVAL;
-}
-
-struct console_font_op32 {
-	compat_uint_t op;        /* operation code KD_FONT_OP_* */
-	compat_uint_t flags;     /* KD_FONT_FLAG_* */
-	compat_uint_t width, height;     /* font size */
-	compat_uint_t charcount;
-	compat_caddr_t data;    /* font data with height fixed to 32 */
-};
-                                        
-static int do_kdfontop_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file)
-{
-	struct console_font_op op;
-	struct console_font_op32 __user *fontop = compat_ptr(arg);
-	int perm = vt_check(file), i;
-	struct vc_data *vc;
-	
-	if (perm < 0) return perm;
-	
-	if (copy_from_user(&op, fontop, sizeof(struct console_font_op32)))
-		return -EFAULT;
-	if (!perm && op.op != KD_FONT_OP_GET)
-		return -EPERM;
-	op.data = compat_ptr(((struct console_font_op32 *)&op)->data);
-	op.flags |= KD_FONT_FLAG_OLD;
-	vc = ((struct tty_struct *)file->private_data)->driver_data;
-	i = con_font_op(vc, &op);
-	if (i)
-		return i;
-	((struct console_font_op32 *)&op)->data = (unsigned long)op.data;
-	if (copy_to_user(fontop, &op, sizeof(struct console_font_op32)))
-		return -EFAULT;
-	return 0;
-}
-
-struct unimapdesc32 {
-	unsigned short entry_ct;
-	compat_caddr_t entries;
-};
-
-static int do_unimap_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file)
-{
-	struct unimapdesc32 tmp;
-	struct unimapdesc32 __user *user_ud = compat_ptr(arg);
-	int perm = vt_check(file);
-	
-	if (perm < 0) return perm;
-	if (copy_from_user(&tmp, user_ud, sizeof tmp))
-		return -EFAULT;
-	switch (cmd) {
-	case PIO_UNIMAP:
-		if (!perm) return -EPERM;
-		return con_set_unimap(vc_cons[fg_console].d, tmp.entry_ct, compat_ptr(tmp.entries));
-	case GIO_UNIMAP:
-		return con_get_unimap(vc_cons[fg_console].d, tmp.entry_ct, &(user_ud->entry_ct), compat_ptr(tmp.entries));
-	}
-	return 0;
-}
-
-#endif /* CONFIG_VT */
-
 static int do_smb_getmountuid(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	mm_segment_t old_fs = get_fs();
@@ -1691,13 +1551,6 @@
 HANDLE_IOCTL(LOOP_GET_STATUS, loop_status)
 #define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93,0x64,unsigned int)
 HANDLE_IOCTL(AUTOFS_IOC_SETTIMEOUT32, ioc_settimeout)
-#ifdef CONFIG_VT
-HANDLE_IOCTL(PIO_FONTX, do_fontx_ioctl)
-HANDLE_IOCTL(GIO_FONTX, do_fontx_ioctl)
-HANDLE_IOCTL(PIO_UNIMAP, do_unimap_ioctl)
-HANDLE_IOCTL(GIO_UNIMAP, do_unimap_ioctl)
-HANDLE_IOCTL(KDFONTOP, do_kdfontop_ioctl)
-#endif
 HANDLE_IOCTL(EXT2_IOC32_GETFLAGS, do_ext2_ioctl)
 HANDLE_IOCTL(EXT2_IOC32_SETFLAGS, do_ext2_ioctl)
 HANDLE_IOCTL(EXT2_IOC32_GETVERSION, do_ext2_ioctl)
Index: linux-2.6.14-rc/include/linux/compat_ioctl.h
===================================================================
--- linux-2.6.14-rc.orig/include/linux/compat_ioctl.h	2005-11-05 02:41:31.000000000 +0100
+++ linux-2.6.14-rc/include/linux/compat_ioctl.h	2005-11-05 02:41:32.000000000 +0100
@@ -10,48 +10,6 @@
 #define ULONG_IOCTL(cmd)  HANDLE_IOCTL((cmd),(ioctl_trans_handler_t)sys_ioctl)
 #endif
 
-/* Big T */
-COMPATIBLE_IOCTL(TCGETA)
-COMPATIBLE_IOCTL(TCSETA)
-COMPATIBLE_IOCTL(TCSETAW)
-COMPATIBLE_IOCTL(TCSETAF)
-COMPATIBLE_IOCTL(TCSBRK)
-ULONG_IOCTL(TCSBRKP)
-COMPATIBLE_IOCTL(TCXONC)
-COMPATIBLE_IOCTL(TCFLSH)
-COMPATIBLE_IOCTL(TCGETS)
-COMPATIBLE_IOCTL(TCSETS)
-COMPATIBLE_IOCTL(TCSETSW)
-COMPATIBLE_IOCTL(TCSETSF)
-COMPATIBLE_IOCTL(TIOCLINUX)
-COMPATIBLE_IOCTL(TIOCSBRK)
-COMPATIBLE_IOCTL(TIOCCBRK)
-ULONG_IOCTL(TIOCMIWAIT)
-COMPATIBLE_IOCTL(TIOCGICOUNT)
-/* Little t */
-COMPATIBLE_IOCTL(TIOCGETD)
-COMPATIBLE_IOCTL(TIOCSETD)
-COMPATIBLE_IOCTL(TIOCEXCL)
-COMPATIBLE_IOCTL(TIOCNXCL)
-COMPATIBLE_IOCTL(TIOCCONS)
-COMPATIBLE_IOCTL(TIOCGSOFTCAR)
-COMPATIBLE_IOCTL(TIOCSSOFTCAR)
-COMPATIBLE_IOCTL(TIOCSWINSZ)
-COMPATIBLE_IOCTL(TIOCGWINSZ)
-COMPATIBLE_IOCTL(TIOCMGET)
-COMPATIBLE_IOCTL(TIOCMBIC)
-COMPATIBLE_IOCTL(TIOCMBIS)
-COMPATIBLE_IOCTL(TIOCMSET)
-COMPATIBLE_IOCTL(TIOCPKT)
-COMPATIBLE_IOCTL(TIOCNOTTY)
-COMPATIBLE_IOCTL(TIOCSTI)
-COMPATIBLE_IOCTL(TIOCOUTQ)
-COMPATIBLE_IOCTL(TIOCSPGRP)
-COMPATIBLE_IOCTL(TIOCGPGRP)
-ULONG_IOCTL(TIOCSCTTY)
-COMPATIBLE_IOCTL(TIOCGPTN)
-COMPATIBLE_IOCTL(TIOCSPTLCK)
-COMPATIBLE_IOCTL(TIOCSERGETLSR)
 /* Big F */
 COMPATIBLE_IOCTL(FBIOBLANK)
 COMPATIBLE_IOCTL(FBIOGET_VSCREENINFO)
@@ -121,37 +79,13 @@
 COMPATIBLE_IOCTL(DM_LIST_VERSIONS)
 COMPATIBLE_IOCTL(DM_TARGET_MSG)
 /* Big K */
-COMPATIBLE_IOCTL(PIO_FONT)
-COMPATIBLE_IOCTL(GIO_FONT)
-ULONG_IOCTL(KDSIGACCEPT)
-COMPATIBLE_IOCTL(KDGETKEYCODE)
-COMPATIBLE_IOCTL(KDSETKEYCODE)
-ULONG_IOCTL(KIOCSOUND)
-ULONG_IOCTL(KDMKTONE)
 COMPATIBLE_IOCTL(KDGKBTYPE)
-ULONG_IOCTL(KDSETMODE)
-COMPATIBLE_IOCTL(KDGETMODE)
-ULONG_IOCTL(KDSKBMODE)
-COMPATIBLE_IOCTL(KDGKBMODE)
-ULONG_IOCTL(KDSKBMETA)
-COMPATIBLE_IOCTL(KDGKBMETA)
 COMPATIBLE_IOCTL(KDGKBENT)
 COMPATIBLE_IOCTL(KDSKBENT)
 COMPATIBLE_IOCTL(KDGKBSENT)
 COMPATIBLE_IOCTL(KDSKBSENT)
 COMPATIBLE_IOCTL(KDGKBDIACR)
 COMPATIBLE_IOCTL(KDSKBDIACR)
-COMPATIBLE_IOCTL(KDKBDREP)
-COMPATIBLE_IOCTL(KDGKBLED)
-ULONG_IOCTL(KDSKBLED)
-COMPATIBLE_IOCTL(KDGETLED)
-ULONG_IOCTL(KDSETLED)
-COMPATIBLE_IOCTL(GIO_SCRNMAP)
-COMPATIBLE_IOCTL(PIO_SCRNMAP)
-COMPATIBLE_IOCTL(GIO_UNISCRNMAP)
-COMPATIBLE_IOCTL(PIO_UNISCRNMAP)
-COMPATIBLE_IOCTL(PIO_FONTRESET)
-COMPATIBLE_IOCTL(PIO_UNIMAPCLR)
 /* Big S */
 COMPATIBLE_IOCTL(SCSI_IOCTL_GET_IDLUN)
 COMPATIBLE_IOCTL(SCSI_IOCTL_DOORLOCK)
@@ -166,19 +100,6 @@
 COMPATIBLE_IOCTL(TUNSETDEBUG)
 COMPATIBLE_IOCTL(TUNSETPERSIST)
 COMPATIBLE_IOCTL(TUNSETOWNER)
-/* Big V */
-COMPATIBLE_IOCTL(VT_SETMODE)
-COMPATIBLE_IOCTL(VT_GETMODE)
-COMPATIBLE_IOCTL(VT_GETSTATE)
-COMPATIBLE_IOCTL(VT_OPENQRY)
-ULONG_IOCTL(VT_ACTIVATE)
-ULONG_IOCTL(VT_WAITACTIVE)
-ULONG_IOCTL(VT_RELDISP)
-ULONG_IOCTL(VT_DISALLOCATE)
-COMPATIBLE_IOCTL(VT_RESIZE)
-COMPATIBLE_IOCTL(VT_RESIZEX)
-COMPATIBLE_IOCTL(VT_LOCKSWITCH)
-COMPATIBLE_IOCTL(VT_UNLOCKSWITCH)
 /* Little v */
 /* Little v, the video4linux ioctls (conflict?) */
 COMPATIBLE_IOCTL(VIDIOCGCAP)
Index: linux-2.6.14-rc/include/linux/tty.h
===================================================================
--- linux-2.6.14-rc.orig/include/linux/tty.h	2005-11-05 02:41:10.000000000 +0100
+++ linux-2.6.14-rc/include/linux/tty.h	2005-11-05 02:41:32.000000000 +0100
@@ -404,6 +404,8 @@
 
 extern int vt_ioctl(struct tty_struct *tty, struct file * file,
 		    unsigned int cmd, unsigned long arg);
+extern int vt_compat_ioctl(struct tty_struct *tty, struct file * file,
+			   unsigned int cmd, unsigned long arg);
 
 static inline dev_t tty_devnum(struct tty_struct *tty)
 {
Index: linux-2.6.14-rc/include/linux/tty_driver.h
===================================================================
--- linux-2.6.14-rc.orig/include/linux/tty_driver.h	2005-11-05 02:41:10.000000000 +0100
+++ linux-2.6.14-rc/include/linux/tty_driver.h	2005-11-05 02:41:32.000000000 +0100
@@ -132,6 +132,8 @@
 	int  (*chars_in_buffer)(struct tty_struct *tty);
 	int  (*ioctl)(struct tty_struct *tty, struct file * file,
 		    unsigned int cmd, unsigned long arg);
+	int  (*compat_ioctl)(struct tty_struct *tty, struct file * file,
+			unsigned int cmd, unsigned long arg);
 	void (*set_termios)(struct tty_struct *tty, struct termios * old);
 	void (*throttle)(struct tty_struct * tty);
 	void (*unthrottle)(struct tty_struct * tty);
@@ -194,6 +196,8 @@
 	int  (*chars_in_buffer)(struct tty_struct *tty);
 	int  (*ioctl)(struct tty_struct *tty, struct file * file,
 		    unsigned int cmd, unsigned long arg);
+	int  (*compat_ioctl)(struct tty_struct *tty, struct file * file,
+		    unsigned int cmd, unsigned long arg);
 	void (*set_termios)(struct tty_struct *tty, struct termios * old);
 	void (*throttle)(struct tty_struct * tty);
 	void (*unthrottle)(struct tty_struct * tty);
Index: linux-2.6.14-rc/drivers/char/tty_io.c
===================================================================
--- linux-2.6.14-rc.orig/drivers/char/tty_io.c	2005-11-05 02:41:10.000000000 +0100
+++ linux-2.6.14-rc/drivers/char/tty_io.c	2005-11-05 02:41:32.000000000 +0100
@@ -95,6 +95,7 @@
 #include <linux/wait.h>
 #include <linux/bitops.h>
 #include <linux/delay.h>
+#include <linux/compat.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -152,6 +153,7 @@
 static int tty_release(struct inode *, struct file *);
 int tty_ioctl(struct inode * inode, struct file * file,
 	      unsigned int cmd, unsigned long arg);
+long tty_compat_ioctl(struct file * file, unsigned int cmd, unsigned long arg);
 static int tty_fasync(int fd, struct file * filp, int on);
 static void release_mem(struct tty_struct *tty, int idx);
 
@@ -680,7 +682,7 @@
 	return POLLIN | POLLOUT | POLLERR | POLLHUP | POLLRDNORM | POLLWRNORM;
 }
 
-static int hung_up_tty_ioctl(struct inode * inode, struct file * file,
+static long hung_up_tty_ioctl(struct file * file,
 			     unsigned int cmd, unsigned long arg)
 {
 	return cmd == TIOCSPGRP ? -ENOTTY : -EIO;
@@ -692,6 +694,9 @@
 	.write		= tty_write,
 	.poll		= tty_poll,
 	.ioctl		= tty_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= tty_compat_ioctl,
+#endif
 	.open		= tty_open,
 	.release	= tty_release,
 	.fasync		= tty_fasync,
@@ -704,6 +709,9 @@
 	.write		= tty_write,
 	.poll		= tty_poll,
 	.ioctl		= tty_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= tty_compat_ioctl,
+#endif
 	.open		= ptmx_open,
 	.release	= tty_release,
 	.fasync		= tty_fasync,
@@ -716,6 +724,9 @@
 	.write		= redirected_tty_write,
 	.poll		= tty_poll,
 	.ioctl		= tty_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= tty_compat_ioctl,
+#endif
 	.open		= tty_open,
 	.release	= tty_release,
 	.fasync		= tty_fasync,
@@ -726,7 +737,8 @@
 	.read		= hung_up_tty_read,
 	.write		= hung_up_tty_write,
 	.poll		= hung_up_tty_poll,
-	.ioctl		= hung_up_tty_ioctl,
+	.unlocked_ioctl	= hung_up_tty_ioctl,
+	.compat_ioctl	= hung_up_tty_ioctl,
 	.release	= tty_release,
 };
 
@@ -2424,6 +2436,99 @@
 }
 
 
+#ifdef CONFIG_COMPAT
+long tty_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct inode *inode = file->f_dentry->d_inode;
+	struct tty_struct *tty;
+	struct tty_ldisc *ld;
+	int ret = -ENOIOCTLCMD;
+
+	/* first handle those that need special treatment */
+	switch (cmd) {
+	case FIONBIO:
+	case TCSBRK:
+	case TIOCCBRK:
+	case TIOCCONS:
+	case TIOCEXCL:
+	case TIOCGETD:
+	case TIOCGPGRP:
+	case TIOCGSID:
+	case TIOCGWINSZ:
+	case TIOCLINUX:
+	case TIOCMBIC:
+	case TIOCMBIS:
+	case TIOCMGET:
+	case TIOCMSET:
+	case TIOCNOTTY:
+	case TIOCNXCL:
+	case TIOCSBRK:
+	case TIOCSETD:
+	case TIOCSPGRP:
+	case TIOCSTI:
+	case TIOCSWINSZ:
+		arg = (unsigned long)compat_ptr(arg);
+	case TCSBRKP:
+	case TIOCSCTTY:
+		lock_kernel();
+		ret = tty_ioctl(inode, file, cmd, arg);
+		unlock_kernel();
+		goto out;
+	}
+
+	/* try to call down to tty specific compat_ioctl method */
+	tty = (struct tty_struct *)file->private_data;
+	if (tty_paranoia_check(tty, inode, "tty_compat_ioctl"))
+		return -EINVAL;
+
+	if (tty->driver->compat_ioctl) {
+		ret = tty->driver->compat_ioctl(tty, file, cmd, arg);
+		if (ret != -ENOIOCTLCMD)
+			goto out;
+	}
+
+	ld = tty_ldisc_ref_wait(tty);
+	if (ld->compat_ioctl) {
+		ret = ld->compat_ioctl(tty, file, cmd, arg);
+	}
+	tty_ldisc_deref(ld);
+
+	if (ret != -ENOIOCTLCMD)
+		goto out;
+
+	/* enter the native code path for those numbers known
+	 * to be compatible */
+	switch (cmd) {
+	case TCFLSH:
+	case TCGETA:
+	case TCGETS:
+	case TCSETA:
+	case TCSETAF:
+	case TCSETAW:
+	case TCSETS:
+	case TCSETSF:
+	case TCSETSW:
+	case TCXONC:
+	case TIOCGICOUNT:
+	case TIOCGPTN:
+	case TIOCGSOFTCAR:
+	case TIOCOUTQ:
+	case TIOCPKT:
+	case TIOCSERGETLSR:
+	case TIOCSPTLCK:
+	case TIOCSSOFTCAR:
+		arg = (unsigned long)compat_ptr(arg);
+	case TIOCMIWAIT:
+		lock_kernel();
+		ret = tty_ioctl(inode, file, cmd, arg);
+		unlock_kernel();
+		break;
+	}
+out:
+	return ret;
+}
+#endif
+
 /*
  * This implements the "Secure Attention Key" ---  the idea is to
  * prevent trojan horses by killing all processes associated with this
@@ -2777,6 +2882,7 @@
 	driver->write_room = op->write_room;
 	driver->chars_in_buffer = op->chars_in_buffer;
 	driver->ioctl = op->ioctl;
+	driver->compat_ioctl = op->compat_ioctl;
 	driver->set_termios = op->set_termios;
 	driver->throttle = op->throttle;
 	driver->unthrottle = op->unthrottle;
Index: linux-2.6.14-rc/include/linux/tty_ldisc.h
===================================================================
--- linux-2.6.14-rc.orig/include/linux/tty_ldisc.h	2005-11-05 02:41:10.000000000 +0100
+++ linux-2.6.14-rc/include/linux/tty_ldisc.h	2005-11-05 02:41:32.000000000 +0100
@@ -126,6 +126,8 @@
 			 const unsigned char * buf, size_t nr);	
 	int	(*ioctl)(struct tty_struct * tty, struct file * file,
 			 unsigned int cmd, unsigned long arg);
+	int	(*compat_ioctl)(struct tty_struct * tty, struct file * file,
+			 unsigned int cmd, unsigned long arg);
 	void	(*set_termios)(struct tty_struct *tty, struct termios * old);
 	unsigned int (*poll)(struct tty_struct *, struct file *,
 			     struct poll_table_struct *);
Index: linux-2.6.14-rc/drivers/char/n_tty.c
===================================================================
--- linux-2.6.14-rc.orig/drivers/char/n_tty.c	2005-11-05 02:41:10.000000000 +0100
+++ linux-2.6.14-rc/drivers/char/n_tty.c	2005-11-05 02:41:32.000000000 +0100
@@ -1549,6 +1549,7 @@
 	read_chan,		/* read */
 	write_chan,		/* write */
 	n_tty_ioctl,		/* ioctl */
+	NULL,			/* compat_ioctl */
 	n_tty_set_termios,	/* set_termios */
 	normal_poll,		/* poll */
 	NULL,			/* hangup */

--

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

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux