Commit 1022068b authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] compat ioctl_table fix

The arch ioctl tables are doing this:

	struct foo ioctl_start[] = {
		...
	};
	struct foo ioctl_end[0];

and fs/compat.c expects that the table lies between &ioctl_end and
&ioctl_start.

Problem is, gcc-3.3 puts ioctl_end into bss, even if it is initialised.  It
doesn't work.

So we do away with the ioctl_end thing and add

	int ioctl_table_length = ARRAY_SIZE(ioctl_start);

to each architecture.
parent 8604173d
......@@ -70,7 +70,7 @@ typedef int (* ioctl32_handler_t)(unsigned int, unsigned int, unsigned long, str
#define IOCTL_TABLE_START \
struct ioctl_trans ioctl_start[] = {
#define IOCTL_TABLE_END \
}; struct ioctl_trans ioctl_end[0];
};
IOCTL_TABLE_START
HANDLE_IOCTL(VFAT_IOCTL_READDIR_BOTH32, vfat_ioctl32)
......@@ -79,3 +79,5 @@ HANDLE_IOCTL(VFAT_IOCTL_READDIR_SHORT32, vfat_ioctl32)
#include "compat_ioctl.c"
#include <linux/compat_ioctl.h>
IOCTL_TABLE_END
int ioctl_table_size = ARRAY_SIZE(ioctl_start);
......@@ -810,8 +810,7 @@ typedef int (* ioctl32_handler_t)(unsigned int, unsigned int, unsigned long, str
#define IOCTL_TABLE_START \
struct ioctl_trans ioctl_start[] = {
#define IOCTL_TABLE_END \
}; struct ioctl_trans ioctl_end[0];
};
IOCTL_TABLE_START
#include <linux/compat_ioctl.h>
......@@ -1206,5 +1205,7 @@ COMPATIBLE_IOCTL(RTC_WKALM_SET)
COMPATIBLE_IOCTL(RTC_WKALM_RD)
IOCTL_TABLE_END
int ioctl_table_size = ARRAY_SIZE(ioctl_start);
#define NR_IOCTL_TRANS (sizeof(ioctl_translations) / \
sizeof(ioctl_translations[0]))
......@@ -2458,7 +2458,7 @@ int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
#define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL(cmd, sys_ioctl)
#define IOCTL_TABLE_START struct ioctl_trans ioctl_start[] = {
#define IOCTL_TABLE_END }; struct ioctl_trans ioctl_end[0];
#define IOCTL_TABLE_END };
IOCTL_TABLE_START
#include <linux/compat_ioctl.h>
......@@ -2631,3 +2631,4 @@ HANDLE_IOCTL(DRM32_IOCTL_RES_CTX, drm32_res_ctx);
#endif /* DRM */
IOCTL_TABLE_END
int ioctl_table_size = ARRAY_SIZE(ioctl_start);
......@@ -725,7 +725,7 @@ static int do_usbdevfs_discsignal(unsigned int fd, unsigned int cmd, unsigned lo
#define IOCTL_TABLE_START \
struct ioctl_trans ioctl_start[] = {
#define IOCTL_TABLE_END \
}; struct ioctl_trans ioctl_end[0];
};
IOCTL_TABLE_START
#include <linux/compat_ioctl.h>
......@@ -763,3 +763,5 @@ HANDLE_IOCTL(USBDEVFS_REAPURB32, do_usbdevfs_reapurb)
HANDLE_IOCTL(USBDEVFS_REAPURBNDELAY32, do_usbdevfs_reapurb)
HANDLE_IOCTL(USBDEVFS_DISCSIGNAL32, do_usbdevfs_discsignal)
IOCTL_TABLE_END
int ioctl_table_size = ARRAY_SIZE(ioctl_start);
......@@ -808,7 +808,7 @@ int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd,
#define IOCTL_TABLE_START \
struct ioctl_trans ioctl_start[] = {
#define IOCTL_TABLE_END \
}; struct ioctl_trans ioctl_end[0];
};
IOCTL_TABLE_START
#include <linux/compat_ioctl.h>
......@@ -899,3 +899,5 @@ HANDLE_IOCTL(BLKSECTGET, w_long)
HANDLE_IOCTL(BLKPG, blkpg_ioctl_trans)
IOCTL_TABLE_END
int ioctl_table_size = ARRAY_SIZE(ioctl_start);
......@@ -1388,7 +1388,7 @@ typedef int (* ioctl32_handler_t)(unsigned int, unsigned int, unsigned long, str
#define IOCTL_TABLE_START \
struct ioctl_trans ioctl_start[] = {
#define IOCTL_TABLE_END \
}; struct ioctl_trans ioctl_end[0];
};
IOCTL_TABLE_START
#include <linux/compat_ioctl.h>
......@@ -1583,3 +1583,5 @@ HANDLE_IOCTL(USBDEVFS_REAPURBNDELAY32, do_usbdevfs_reapurb)
HANDLE_IOCTL(USBDEVFS_DISCSIGNAL32, do_usbdevfs_discsignal)
/* take care of sizeof(sizeof()) breakage */
IOCTL_TABLE_END
int ioctl_table_size = ARRAY_SIZE(ioctl_start);
......@@ -673,12 +673,10 @@ static int mtrr_ioctl32(unsigned int fd, unsigned int cmd, unsigned long arg)
return err;
}
#define REF_SYMBOL(handler) if (0) (void)handler;
#define HANDLE_IOCTL2(cmd,handler) REF_SYMBOL(handler); asm volatile(".quad %P0, " #handler ",0"::"i" (cmd));
#define HANDLE_IOCTL(cmd,handler) HANDLE_IOCTL2(cmd,handler)
#define HANDLE_IOCTL(cmd,handler) { (cmd), (ioctl_trans_handler_t)(handler), NULL },
#define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL(cmd,sys_ioctl)
#define IOCTL_TABLE_START void ioctl_dummy(void) { asm volatile("\n.global ioctl_start\nioctl_start:\n\t" );
#define IOCTL_TABLE_END asm volatile("\n.global ioctl_end;\nioctl_end:\n"); }
#define IOCTL_TABLE_START struct ioctl_trans ioctl_start[] = {
#define IOCTL_TABLE_END };
IOCTL_TABLE_START
#include <linux/compat_ioctl.h>
......@@ -765,3 +763,4 @@ HANDLE_IOCTL(MTRRIOC32_GET_PAGE_ENTRY, mtrr_ioctl32)
HANDLE_IOCTL(MTRRIOC32_KILL_PAGE_ENTRY, mtrr_ioctl32)
IOCTL_TABLE_END
int ioctl_table_size = ARRAY_SIZE(ioctl_start);
......@@ -227,7 +227,8 @@ asmlinkage long compat_fstatfs64(unsigned int fd, struct compat_statfs64 *buf)
#define IOCTL_HASHSIZE 256
struct ioctl_trans *ioctl32_hash_table[IOCTL_HASHSIZE];
extern struct ioctl_trans ioctl_start[], ioctl_end[];
extern struct ioctl_trans ioctl_start[];
extern int ioctl_table_size;
static inline unsigned long ioctl32_hash(unsigned long cmd)
{
......@@ -255,7 +256,7 @@ static int __init init_sys32_ioctl(void)
{
int i;
for (i = 0; &ioctl_start[i] < &ioctl_end[0]; i++) {
for (i = 0; i < ioctl_table_size; i++) {
if (ioctl_start[i].next != 0) {
printk("ioctl translation %d bad\n",i);
return -1;
......@@ -318,8 +319,7 @@ int register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int, u
static inline int builtin_ioctl(struct ioctl_trans *t)
{
return t >= (struct ioctl_trans *)ioctl_start &&
t < (struct ioctl_trans *)ioctl_end;
return t >= ioctl_start && t < (ioctl_start + ioctl_table_size);
}
/* Problem:
......
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