Commit b723d4e1 authored by Laszlo Valko's avatar Laszlo Valko Committed by James Morris

[SPARC64]: Translate IPT_SO_SET_REPLACE socket option for 32-bit apps.

parent ae4d9837
......@@ -53,6 +53,7 @@
#include <linux/security.h>
#include <linux/compat.h>
#include <linux/vfs.h>
#include <linux/netfilter_ipv4/ip_tables.h>
#include <asm/types.h>
#include <asm/ipc.h>
......@@ -2527,6 +2528,78 @@ asmlinkage int sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int use
extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
char *optval, int optlen);
static int do_netfilter_replace(int fd, int level, int optname,
char *optval, int optlen)
{
struct ipt_replace32 {
char name[IPT_TABLE_MAXNAMELEN];
__u32 valid_hooks;
__u32 num_entries;
__u32 size;
__u32 hook_entry[NF_IP_NUMHOOKS];
__u32 underflow[NF_IP_NUMHOOKS];
__u32 num_counters;
__u32 counters;
struct ipt_entry entries[0];
} *repl32 = (struct ipt_replace32 *)optval;
struct ipt_replace *krepl;
struct ipt_counters *counters32;
__u32 origsize;
unsigned int kreplsize, kcountersize;
mm_segment_t old_fs;
int ret;
if (optlen < sizeof(repl32))
return -EINVAL;
if (copy_from_user(&origsize,
&repl32->size,
sizeof(origsize)))
return -EFAULT;
kreplsize = sizeof(*krepl) + origsize;
kcountersize = krepl->num_counters * sizeof(struct ipt_counters);
/* Hack: Causes ipchains to give correct error msg --RR */
if (optlen != kreplsize)
return -ENOPROTOOPT;
krepl = (struct ipt_replace *)kmalloc(kreplsize, GFP_KERNEL);
if (krepl == NULL)
return -ENOMEM;
if (copy_from_user(krepl, optval, kreplsize)) {
kfree(krepl);
return -EFAULT;
}
counters32 = (struct ipt_counters *)AA(
((struct ipt_replace32 *)krepl)->counters);
kcountersize = krepl->num_counters * sizeof(struct ipt_counters);
krepl->counters = (struct ipt_counters *)kmalloc(
kcountersize, GFP_KERNEL);
if (krepl->counters == NULL) {
kfree(krepl);
return -ENOMEM;
}
old_fs = get_fs();
set_fs(KERNEL_DS);
ret = sys_setsockopt(fd, level, optname,
(char *)krepl, kreplsize);
set_fs(old_fs);
if (ret == 0 &&
copy_to_user(counters32, krepl->counters, kcountersize))
ret = -EFAULT;
kfree(krepl->counters);
kfree(krepl);
return ret;
}
static int do_set_attach_filter(int fd, int level, int optname,
char *optval, int optlen)
{
......@@ -2620,6 +2693,9 @@ static int do_set_sock_timeout(int fd, int level, int optname, char *optval, int
asmlinkage int sys32_setsockopt(int fd, int level, int optname,
char *optval, int optlen)
{
if (optname == IPT_SO_SET_REPLACE)
return do_netfilter_replace(fd, level, optname,
optval, optlen);
if (optname == SO_ATTACH_FILTER)
return do_set_attach_filter(fd, level, optname,
optval, optlen);
......
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