geoip: use local-portable aligned_u64 pointer values

A 64-bit kernel will interpret the pointer with 64 bits width, while
a 32-bit userspace filled in only 32 of it, leaving the other 32
undefined. This must be avoided.
This commit is contained in:
Jan Engelhardt
2008-03-18 03:12:07 +01:00
parent fd5321c7d8
commit 7aae90da5a
3 changed files with 11 additions and 12 deletions

View File

@@ -56,7 +56,7 @@ struct geoip_index {
u_int32_t offset; u_int32_t offset;
} __attribute__ ((packed)); } __attribute__ ((packed));
struct geoip_subnet * static struct geoip_subnet *
get_country_subnets(u_int16_t cc, u_int32_t *count) get_country_subnets(u_int16_t cc, u_int32_t *count)
{ {
FILE *ixfd, *dbfd; FILE *ixfd, *dbfd;
@@ -122,8 +122,7 @@ get_country_subnets(u_int16_t cc, u_int32_t *count)
return subnets; return subnets;
} }
static struct geoip_country_user * static struct geoip_country_user *geoip_load_cc(unsigned short cc)
load_geoip_cc(u_int16_t cc)
{ {
struct geoip_country_user *ginfo; struct geoip_country_user *ginfo;
ginfo = malloc(sizeof(struct geoip_country_user)); ginfo = malloc(sizeof(struct geoip_country_user));
@@ -131,7 +130,7 @@ load_geoip_cc(u_int16_t cc)
if (!ginfo) if (!ginfo)
return NULL; return NULL;
ginfo->subnets = get_country_subnets(cc, &ginfo->count); ginfo->subnets = (unsigned long)get_country_subnets(cc, &ginfo->count);
ginfo->cc = cc; ginfo->cc = cc;
return ginfo; return ginfo;
@@ -173,9 +172,8 @@ check_geoip_cc(char *cc, u_int16_t cc_used[], u_int8_t count)
return cc_int16; return cc_int16;
} }
/* Based on libipt_multiport.c parsing code. */ static unsigned int parse_geoip_cc(const char *ccstr, uint16_t *cc,
static u_int8_t union geoip_country_group *mem)
parse_geoip_cc(const char *ccstr, u_int16_t *cc, union geoip_country_group *mem)
{ {
char *buffer, *cp, *next; char *buffer, *cp, *next;
u_int8_t i, count = 0; u_int8_t i, count = 0;
@@ -192,7 +190,7 @@ parse_geoip_cc(const char *ccstr, u_int16_t *cc, union geoip_country_group *mem)
if (next) *next++ = '\0'; if (next) *next++ = '\0';
if ((cctmp = check_geoip_cc(cp, cc, count)) != 0) { if ((cctmp = check_geoip_cc(cp, cc, count)) != 0) {
if ((mem[count++].user = load_geoip_cc(cctmp)) == NULL) if ((mem[count++].user = (unsigned long)geoip_load_cc(cctmp)) == 0)
exit_error(OTHER_PROBLEM, exit_error(OTHER_PROBLEM,
"geoip: insufficient memory available"); "geoip: insufficient memory available");
cc[count-1] = cctmp; cc[count-1] = cctmp;

View File

@@ -59,7 +59,8 @@ geoip_add_node(const struct geoip_country_user __user *umem_ptr)
s = vmalloc(p->count * sizeof(struct geoip_subnet)); s = vmalloc(p->count * sizeof(struct geoip_subnet));
if (s == NULL) if (s == NULL)
goto free_p; goto free_p;
if (copy_from_user(s, umem.subnets, p->count * sizeof(struct geoip_subnet)) != 0) if (copy_from_user(s, (const void __user *)(unsigned long)umem.subnets,
p->count * sizeof(struct geoip_subnet)) != 0)
goto free_s; goto free_s;
spin_lock_bh(&geoip_lock); spin_lock_bh(&geoip_lock);
@@ -189,7 +190,7 @@ static bool xt_geoip_mt_checkentry(const char *table, const void *entry,
for (i = 0; i < info->count; i++) { for (i = 0; i < info->count; i++) {
node = find_node(info->cc[i]); node = find_node(info->cc[i]);
if (node == NULL) if (node == NULL)
if ((node = geoip_add_node(info->mem[i].user)) == NULL) { if ((node = geoip_add_node((const void __user *)(unsigned long)info->mem[i].user)) == NULL) {
printk(KERN_ERR printk(KERN_ERR
"xt_geoip: unable to load '%c%c' into memory\n", "xt_geoip: unable to load '%c%c' into memory\n",
COUNTRY(info->cc[i])); COUNTRY(info->cc[i]));

View File

@@ -25,7 +25,7 @@ struct geoip_subnet {
}; };
struct geoip_country_user { struct geoip_country_user {
struct geoip_subnet *subnets; aligned_u64 subnets;
u_int32_t count; u_int32_t count;
u_int16_t cc; u_int16_t cc;
}; };
@@ -33,7 +33,7 @@ struct geoip_country_user {
struct geoip_country_kernel; struct geoip_country_kernel;
union geoip_country_group { union geoip_country_group {
struct geoip_country_user *user; aligned_u64 user;
struct geoip_country_kernel *kernel; struct geoip_country_kernel *kernel;
}; };