Commit 3225fc8a authored by Benjamin LaHaise's avatar Benjamin LaHaise Committed by David S. Miller

[NET]: Simplify scm handling and sendmsg/recvmsg invocation, consolidate net compat syscalls.

1) Pull scm argument from sendmsg/recvmsg, it is available
from I/O control block
2) Consolidate networking syscall compat call into net/compat.c
3) Change ops->{sendmsg,recvmsg}() code sequences into sock_{sendmsg,recvmsg}()
parent 8589b566
......@@ -300,7 +300,7 @@ ia32_syscall_table:
data8 compat_sys_statfs
data8 compat_sys_fstatfs /* 100 */
data8 sys32_ioperm
data8 sys32_socketcall
data8 compat_sys_socketcall
data8 sys_syslog
data8 compat_sys_setitimer
data8 compat_sys_getitimer /* 105 */
......
......@@ -97,11 +97,9 @@ typedef struct sg_io_hdr32 {
int info; /* [o] auxiliary information */
} sg_io_hdr32_t; /* 64 bytes long (on IA32) */
struct iovec32 { unsigned int iov_base; int iov_len; };
static int alloc_sg_iovec(sg_io_hdr_t *sgp, int uptr32)
{
struct iovec32 *uiov = (struct iovec32 *) P(uptr32);
struct compat_iovec *uiov = (struct compat_iovec *) P(uptr32);
sg_iovec_t *kiov;
int i;
......@@ -136,7 +134,7 @@ static int alloc_sg_iovec(sg_io_hdr_t *sgp, int uptr32)
static int copy_back_sg_iovec(sg_io_hdr_t *sgp, int uptr32)
{
struct iovec32 *uiov = (struct iovec32 *) P(uptr32);
struct compat_iovec *uiov = (struct compat_iovec *) P(uptr32);
sg_iovec_t *kiov = (sg_iovec_t *) sgp->dxferp;
int i;
......
This diff is collapsed.
......@@ -729,12 +729,10 @@ extern asmlinkage int sys32_llseek(unsigned int fd, unsigned int offset_high,
return sys_llseek(fd, offset_high, offset_low, result, origin);
}
struct iovec32 { unsigned int iov_base; int iov_len; };
typedef ssize_t (*IO_fn_t)(struct file *, char *, size_t, loff_t *);
static long
do_readv_writev32(int type, struct file *file, const struct iovec32 *vector,
do_readv_writev32(int type, struct file *file, const struct compat_iovec *vector,
u32 count)
{
unsigned long tot_len;
......@@ -749,7 +747,7 @@ do_readv_writev32(int type, struct file *file, const struct iovec32 *vector,
*/
if (!count)
return 0;
if(verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count))
if(verify_area(VERIFY_READ, vector, sizeof(struct compat_iovec)*count))
return -EFAULT;
if (count > UIO_MAXIOV)
return -EINVAL;
......@@ -835,7 +833,7 @@ do_readv_writev32(int type, struct file *file, const struct iovec32 *vector,
}
asmlinkage long
sys32_readv(int fd, struct iovec32 *vector, u32 count)
sys32_readv(int fd, struct compat_iovec *vector, u32 count)
{
struct file *file;
ssize_t ret;
......@@ -855,7 +853,7 @@ sys32_readv(int fd, struct iovec32 *vector, u32 count)
}
asmlinkage long
sys32_writev(int fd, struct iovec32 *vector, u32 count)
sys32_writev(int fd, struct compat_iovec *vector, u32 count)
{
struct file *file;
ssize_t ret;
......@@ -1155,48 +1153,6 @@ asmlinkage long sys32_times(struct tms32 *tbuf)
return ret;
}
extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
char *optval, int optlen);
asmlinkage int sys32_setsockopt(int fd, int level, int optname,
char *optval, int optlen)
{
if (optname == SO_ATTACH_FILTER) {
struct sock_fprog32 {
__u16 len;
__u32 filter;
} *fprog32 = (struct sock_fprog32 *)optval;
struct sock_fprog kfprog;
struct sock_filter *kfilter;
unsigned int fsize;
mm_segment_t old_fs;
__u32 uptr;
int ret;
if (get_user(kfprog.len, &fprog32->len) ||
__get_user(uptr, &fprog32->filter))
return -EFAULT;
kfprog.filter = (struct sock_filter *)A(uptr);
fsize = kfprog.len * sizeof(struct sock_filter);
kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL);
if (kfilter == NULL)
return -ENOMEM;
if (copy_from_user(kfilter, kfprog.filter, fsize)) {
kfree(kfilter);
return -EFAULT;
}
kfprog.filter = kfilter;
old_fs = get_fs();
set_fs(KERNEL_DS);
ret = sys_setsockopt(fd, level, optname,
(char *)&kfprog, sizeof(kfprog));
set_fs(old_fs);
kfree(kfilter);
return ret;
}
return sys_setsockopt(fd, level, optname, optval, optlen);
}
struct flock32 {
short l_type;
short l_whence;
......@@ -1873,256 +1829,3 @@ asmlinkage int sys32_adjtimex(struct timex32 *utp)
return ret;
}
/*
* Declare the 32-bit version of the msghdr
*/
struct msghdr32 {
unsigned int msg_name; /* Socket name */
int msg_namelen; /* Length of name */
unsigned int msg_iov; /* Data blocks */
unsigned int msg_iovlen; /* Number of blocks */
unsigned int msg_control; /* Per protocol magic (eg BSD file descriptor passing) */
unsigned int msg_controllen; /* Length of cmsg list */
unsigned msg_flags;
};
static inline int
shape_msg(struct msghdr *mp, struct msghdr32 *mp32)
{
int ret;
unsigned int i;
if (!access_ok(VERIFY_READ, mp32, sizeof(*mp32)))
return(-EFAULT);
ret = __get_user(i, &mp32->msg_name);
mp->msg_name = (void *)A(i);
ret |= __get_user(mp->msg_namelen, &mp32->msg_namelen);
ret |= __get_user(i, &mp32->msg_iov);
mp->msg_iov = (struct iovec *)A(i);
ret |= __get_user(mp->msg_iovlen, &mp32->msg_iovlen);
ret |= __get_user(i, &mp32->msg_control);
mp->msg_control = (void *)A(i);
ret |= __get_user(mp->msg_controllen, &mp32->msg_controllen);
ret |= __get_user(mp->msg_flags, &mp32->msg_flags);
return(ret ? -EFAULT : 0);
}
/*
* Verify & re-shape IA32 iovec. The caller must ensure that the
* iovec is big enough to hold the re-shaped message iovec.
*
* Save time not doing verify_area. copy_*_user will make this work
* in any case.
*
* Don't need to check the total size for overflow (cf net/core/iovec.c),
* 32-bit sizes can't overflow a 64-bit count.
*/
static inline int
verify_iovec32(struct msghdr *m, struct iovec *iov, char *address, int mode)
{
int size, err, ct;
struct iovec32 *iov32;
if(m->msg_namelen)
{
if(mode==VERIFY_READ)
{
err=move_addr_to_kernel(m->msg_name, m->msg_namelen, address);
if(err<0)
goto out;
}
m->msg_name = address;
} else
m->msg_name = NULL;
err = -EFAULT;
size = m->msg_iovlen * sizeof(struct iovec32);
if (copy_from_user(iov, m->msg_iov, size))
goto out;
m->msg_iov=iov;
err = 0;
iov32 = (struct iovec32 *)iov;
for (ct = m->msg_iovlen; ct-- > 0; ) {
iov[ct].iov_len = (__kernel_size_t)iov32[ct].iov_len;
iov[ct].iov_base = (void *) A(iov32[ct].iov_base);
err += iov[ct].iov_len;
}
out:
return err;
}
/* XXX This really belongs in some header file... -DaveM */
#define MAX_SOCK_ADDR 128 /* 108 for Unix domain -
16 for IP, 16 for IPX,
24 for IPv6,
about 80 for AX.25 */
/*
* BSD sendmsg interface
*/
int sys32_sendmsg(int fd, struct msghdr32 *msg, unsigned flags)
{
struct socket *sock;
char address[MAX_SOCK_ADDR];
struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
unsigned char ctl[sizeof(struct cmsghdr) + 20]; /* 20 is size of ipv6_pktinfo */
unsigned char *ctl_buf = ctl;
struct msghdr msg_sys;
int err, ctl_len, iov_size, total_len;
err = -EFAULT;
if (shape_msg(&msg_sys, msg))
goto out;
sock = sockfd_lookup(fd, &err);
if (!sock)
goto out;
/* do not move before msg_sys is valid */
err = -EINVAL;
if (msg_sys.msg_iovlen > UIO_MAXIOV)
goto out_put;
/* Check whether to allocate the iovec area*/
err = -ENOMEM;
iov_size = msg_sys.msg_iovlen * sizeof(struct iovec32);
if (msg_sys.msg_iovlen > UIO_FASTIOV) {
iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
if (!iov)
goto out_put;
}
/* This will also move the address data into kernel space */
err = verify_iovec32(&msg_sys, iov, address, VERIFY_READ);
if (err < 0)
goto out_freeiov;
total_len = err;
err = -ENOBUFS;
if (msg_sys.msg_controllen > INT_MAX)
goto out_freeiov;
ctl_len = msg_sys.msg_controllen;
if (ctl_len)
{
if (ctl_len > sizeof(ctl))
{
err = -ENOBUFS;
ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);
if (ctl_buf == NULL)
goto out_freeiov;
}
err = -EFAULT;
if (copy_from_user(ctl_buf, msg_sys.msg_control, ctl_len))
goto out_freectl;
msg_sys.msg_control = ctl_buf;
}
msg_sys.msg_flags = flags;
if (sock->file->f_flags & O_NONBLOCK)
msg_sys.msg_flags |= MSG_DONTWAIT;
err = sock_sendmsg(sock, &msg_sys, total_len);
out_freectl:
if (ctl_buf != ctl)
sock_kfree_s(sock->sk, ctl_buf, ctl_len);
out_freeiov:
if (iov != iovstack)
sock_kfree_s(sock->sk, iov, iov_size);
out_put:
sockfd_put(sock);
out:
return err;
}
/*
* BSD recvmsg interface
*/
int
sys32_recvmsg (int fd, struct msghdr32 *msg, unsigned int flags)
{
struct socket *sock;
struct iovec iovstack[UIO_FASTIOV];
struct iovec *iov=iovstack;
struct msghdr msg_sys;
unsigned long cmsg_ptr;
int err, iov_size, total_len, len;
/* kernel mode address */
char addr[MAX_SOCK_ADDR];
/* user mode address pointers */
struct sockaddr *uaddr;
int *uaddr_len;
err=-EFAULT;
if (shape_msg(&msg_sys, msg))
goto out;
sock = sockfd_lookup(fd, &err);
if (!sock)
goto out;
err = -EINVAL;
if (msg_sys.msg_iovlen > UIO_MAXIOV)
goto out_put;
/* Check whether to allocate the iovec area*/
err = -ENOMEM;
iov_size = msg_sys.msg_iovlen * sizeof(struct iovec);
if (msg_sys.msg_iovlen > UIO_FASTIOV) {
iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
if (!iov)
goto out_put;
}
/*
* Save the user-mode address (verify_iovec will change the
* kernel msghdr to use the kernel address space)
*/
uaddr = msg_sys.msg_name;
uaddr_len = &msg->msg_namelen;
err = verify_iovec32(&msg_sys, iov, addr, VERIFY_WRITE);
if (err < 0)
goto out_freeiov;
total_len=err;
cmsg_ptr = (unsigned long)msg_sys.msg_control;
msg_sys.msg_flags = 0;
if (sock->file->f_flags & O_NONBLOCK)
flags |= MSG_DONTWAIT;
err = sock_recvmsg(sock, &msg_sys, total_len, flags);
if (err < 0)
goto out_freeiov;
len = err;
if (uaddr != NULL) {
err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len);
if (err < 0)
goto out_freeiov;
}
err = __put_user(msg_sys.msg_flags, &msg->msg_flags);
if (err)
goto out_freeiov;
err = __put_user((unsigned long)msg_sys.msg_control-cmsg_ptr,
&msg->msg_controllen);
if (err)
goto out_freeiov;
err = len;
out_freeiov:
if (iov != iovstack)
sock_kfree_s(sock->sk, iov, iov_size);
out_put:
sockfd_put(sock);
out:
return err;
}
......@@ -378,8 +378,8 @@ illegal_syscall:
sys sys32_select 5
sys sys_flock 2
sys sys_msync 3
sys sys32_readv 3 /* 4145 */
sys sys32_writev 3
sys compat_sys_readv 3 /* 4145 */
sys compat_sys_writev 3
sys sys_cacheflush 3
sys sys_cachectl 3
sys sys_sysmips 4
......@@ -410,11 +410,11 @@ illegal_syscall:
sys sys_listen 2
sys sys_recv 4 /* 4175 */
sys sys_recvfrom 6
sys sys32_recvmsg 3
sys compat_sys_recvmsg 3
sys sys_send 4
sys sys32_sendmsg 3
sys compat_sys_sendmsg 3
sys sys_sendto 6 /* 4180 */
sys sys32_setsockopt 5
sys compat_sys_setsockopt 5
sys sys_shutdown 2
sys sys_socket 3
sys sys_socketpair 4
......
This diff is collapsed.
......@@ -604,7 +604,7 @@ _GLOBAL(sys_call_table32)
.llong .compat_sys_statfs
.llong .compat_sys_fstatfs /* 100 */
.llong .sys_ioperm
.llong .sys32_socketcall
.llong .compat_sys_socketcall
.llong .sys32_syslog
.llong .compat_sys_setitimer
.llong .compat_sys_getitimer /* 105 */
......
......@@ -25,7 +25,7 @@ _GLOBAL(ppc32_lseek)
extsw r4,r4 /* sign extend off_t offset parm */
b .sys_lseek
_GLOBAL(sys32_socketcall) /* r3=call, r4=args */
_GLOBAL(compat_sys_socketcall) /* r3=call, r4=args */
cmpwi r3, 1
blt- .do_einval
cmpwi r3, 17
......@@ -221,14 +221,14 @@ _STATIC(do_sys_shutdown) /* sys_shutdown(int, int) */
.llong 2b,.do_efault
.previous
_STATIC(do_sys_setsockopt) /* sys32_setsockopt(int, int, int, char *, int) */
_STATIC(do_sys_setsockopt) /* compat_sys_setsockopt(int, int, int, char *, int) */
mr r10,r4
1: lwa r3,0(r10)
2: lwa r4,4(r10)
3: lwa r5,8(r10)
4: lwz r6,12(r10)
5: lwa r7,16(r10)
b .sys32_setsockopt
b .compat_sys_setsockopt
.section __ex_table,"a"
.align 3
.llong 1b,.do_efault
......@@ -238,14 +238,14 @@ _STATIC(do_sys_setsockopt) /* sys32_setsockopt(int, int, int, char *, int) */
.llong 5b,.do_efault
.previous
_STATIC(do_sys_getsockopt) /* sys32_getsockopt(int, int, int, u32, u32) */
_STATIC(do_sys_getsockopt) /* compat_sys_getsockopt(int, int, int, u32, u32) */
mr r10,r4
1: lwa r3,0(r10)
2: lwa r4,4(r10)
3: lwa r5,8(r10)
4: lwz r6,12(r10)
5: lwz r7,16(r10)
b .sys32_getsockopt
b .compat_sys_getsockopt
.section __ex_table,"a"
.align 3
.llong 1b,.do_efault
......@@ -255,12 +255,12 @@ _STATIC(do_sys_getsockopt) /* sys32_getsockopt(int, int, int, u32, u32) */
.llong 5b,.do_efault
.previous
_STATIC(do_sys_sendmsg) /* sys32_sendmsg(int, struct msghdr32 *, unsigned int) */
_STATIC(do_sys_sendmsg) /* compat_sys_sendmsg(int, struct compat_msghdr *, unsigned int) */
mr r10,r4
1: lwa r3,0(r10)
2: lwz r4,4(r10)
3: lwa r5,8(r10)
b .sys32_sendmsg
b .compat_sys_sendmsg
.section __ex_table,"a"
.align 3
.llong 1b,.do_efault
......@@ -268,12 +268,12 @@ _STATIC(do_sys_sendmsg) /* sys32_sendmsg(int, struct msghdr32 *, unsigned int) *
.llong 3b,.do_efault
.previous
_STATIC(do_sys_recvmsg) /* sys32_recvmsg(int, struct msghdr32 *, unsigned int) */
_STATIC(do_sys_recvmsg) /* compat_sys_recvmsg(int, struct compat_msghdr *, unsigned int) */
mr r10,r4
1: lwa r3,0(r10)
2: lwz r4,4(r10)
3: lwa r5,8(r10)
b .sys32_recvmsg
b .compat_sys_recvmsg
.section __ex_table,"a"
.align 3
.llong 1b,.do_efault
......
This diff is collapsed.
......@@ -499,7 +499,7 @@ sys_call_table:
.long SYSCALL(sys_statfs,compat_sys_statfs_wrapper)
.long SYSCALL(sys_fstatfs,compat_sys_fstatfs_wrapper) /* 100 */
.long SYSCALL(sys_ni_syscall,sys_ni_syscall)
.long SYSCALL(sys_socketcall,sys32_socketcall_wrapper)
.long SYSCALL(sys_socketcall,compat_sys_socketcall_wrapper)
.long SYSCALL(sys_syslog,sys32_syslog_wrapper)
.long SYSCALL(sys_setitimer,compat_sys_setitimer_wrapper)
.long SYSCALL(sys_getitimer,compat_sys_getitimer_wrapper) /* 105 */
......
This diff is collapsed.
......@@ -452,11 +452,11 @@ compat_sys_fstatfs_wrapper:
llgtr %r3,%r3 # struct compat_statfs *
jg compat_sys_fstatfs # branch to system call
.globl sys32_socketcall_wrapper
sys32_socketcall_wrapper:
.globl compat_sys_socketcall_wrapper
compat_sys_socketcall_wrapper:
lgfr %r2,%r2 # int
llgtr %r3,%r3 # u32 *
jg sys32_socketcall # branch to system call
jg compat_sys_socketcall # branch to system call
.globl sys32_syslog_wrapper
sys32_syslog_wrapper:
......
......@@ -202,38 +202,38 @@ do_sys_shutdown: /* sys_shutdown(int, int) */
nop
nop
nop
do_sys_setsockopt: /* sys32_setsockopt(int, int, int, char *, int) */
do_sys_setsockopt: /* compat_sys_setsockopt(int, int, int, char *, int) */
ldswa [%o1 + 0x0] %asi, %o0
sethi %hi(sys32_setsockopt), %g1
sethi %hi(compat_sys_setsockopt), %g1
ldswa [%o1 + 0x8] %asi, %o2
lduwa [%o1 + 0xc] %asi, %o3
ldswa [%o1 + 0x10] %asi, %o4
jmpl %g1 + %lo(sys32_setsockopt), %g0
jmpl %g1 + %lo(compat_sys_setsockopt), %g0
ldswa [%o1 + 0x4] %asi, %o1
nop
do_sys_getsockopt: /* sys32_getsockopt(int, int, int, u32, u32) */
do_sys_getsockopt: /* compat_sys_getsockopt(int, int, int, u32, u32) */
ldswa [%o1 + 0x0] %asi, %o0
sethi %hi(sys32_getsockopt), %g1
sethi %hi(compat_sys_getsockopt), %g1
ldswa [%o1 + 0x8] %asi, %o2
lduwa [%o1 + 0xc] %asi, %o3
lduwa [%o1 + 0x10] %asi, %o4
jmpl %g1 + %lo(sys32_getsockopt), %g0
jmpl %g1 + %lo(compat_sys_getsockopt), %g0
ldswa [%o1 + 0x4] %asi, %o1
nop
do_sys_sendmsg: /* sys32_sendmsg(int, struct msghdr32 *, unsigned int) */
do_sys_sendmsg: /* compat_sys_sendmsg(int, struct compat_msghdr *, unsigned int) */
ldswa [%o1 + 0x0] %asi, %o0
sethi %hi(sys32_sendmsg), %g1
sethi %hi(compat_sys_sendmsg), %g1
lduwa [%o1 + 0x8] %asi, %o2
jmpl %g1 + %lo(sys32_sendmsg), %g0
jmpl %g1 + %lo(compat_sys_sendmsg), %g0
lduwa [%o1 + 0x4] %asi, %o1
nop
nop
nop
do_sys_recvmsg: /* sys32_recvmsg(int, struct msghdr32 *, unsigned int) */
do_sys_recvmsg: /* compat_sys_recvmsg(int, struct compat_msghdr *, unsigned int) */
ldswa [%o1 + 0x0] %asi, %o0
sethi %hi(sys32_recvmsg), %g1
sethi %hi(compat_sys_recvmsg), %g1
lduwa [%o1 + 0x8] %asi, %o2
jmpl %g1 + %lo(sys32_recvmsg), %g0
jmpl %g1 + %lo(compat_sys_recvmsg), %g0
lduwa [%o1 + 0x4] %asi, %o1
nop
nop
......
This diff is collapsed.
......@@ -54,6 +54,7 @@
#include <linux/personality.h>
/* For SOCKET_I */
#include <linux/socket.h>
#include <net/sock.h>
/* Use this to get at 32-bit user passed pointers. */
......@@ -1324,8 +1325,6 @@ asmlinkage int sunos_sigaction (int sig, u32 act, u32 oact)
extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
char *optval, int optlen);
extern asmlinkage int sys32_getsockopt(int fd, int level, int optname,
u32 optval, u32 optlen);
asmlinkage int sunos_setsockopt(int fd, int level, int optname, u32 optval,
int optlen)
......@@ -1353,6 +1352,6 @@ asmlinkage int sunos_getsockopt(int fd, int level, int optname,
if (tr_opt >=2 && tr_opt <= 6)
tr_opt += 30;
}
ret = sys32_getsockopt(fd, level, tr_opt, optval, optlen);
ret = compat_sys_getsockopt(fd, level, tr_opt, (void*)(unsigned long)optval, (void*)(unsigned long)optlen);
return ret;
}
......@@ -179,7 +179,7 @@ sunos_sys_table:
.word sunos_nosys, sys_bind, sunos_setsockopt
.word sys_listen, sunos_nosys, sunos_sigaction
.word sunos_sigblock, sunos_sigsetmask, sys_sigpause
.word sys32_sigstack, sys32_recvmsg, sys32_sendmsg
.word sys32_sigstack, compat_sys_recvmsg, compat_sys_sendmsg
.word sunos_nosys, sys32_gettimeofday, sys32_getrusage
.word sunos_getsockopt, sunos_nosys, sunos_readv
.word sunos_writev, sys32_settimeofday, sys32_fchown16
......
......@@ -267,13 +267,8 @@ struct sol_cmsghdr {
unsigned char cmsg_data[0];
};
struct iovec32 {
u32 iov_base;
u32 iov_len;
};
static inline int iov_from_user32_to_kern(struct iovec *kiov,
struct iovec32 *uiov32,
struct compat_iovec *uiov32,
int niov)
{
int tot_len = 0;
......@@ -322,7 +317,7 @@ static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg,
}
/* I've named the args so it is easy to tell whose space the pointers are in. */
static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov,
static int verify_compat_iovec(struct msghdr *kern_msg, struct iovec *kern_iov,
char *kern_address, int mode)
{
int tot_len;
......@@ -347,7 +342,7 @@ static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov,
}
tot_len = iov_from_user32_to_kern(kern_iov,
(struct iovec32 *)kern_msg->msg_iov,
(struct compat_iovec *)kern_msg->msg_iov,
kern_msg->msg_iovlen);
if(tot_len >= 0)
kern_msg->msg_iov = kern_iov;
......@@ -371,7 +366,7 @@ asmlinkage int solaris_sendmsg(int fd, struct sol_nmsghdr *user_msg, unsigned us
return -EFAULT;
if(kern_msg.msg_iovlen > UIO_MAXIOV)
return -EINVAL;
err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ);
err = verify_compat_iovec(&kern_msg, iov, address, VERIFY_READ);
if (err < 0)
goto out;
total_len = err;
......@@ -439,7 +434,7 @@ asmlinkage int solaris_recvmsg(int fd, struct sol_nmsghdr *user_msg, unsigned in
uaddr = kern_msg.msg_name;
uaddr_len = &user_msg->msg_namelen;
err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE);
err = verify_compat_iovec(&kern_msg, iov, addr, VERIFY_WRITE);
if (err < 0)
goto out;
total_len = err;
......
......@@ -4,4 +4,4 @@
obj-$(CONFIG_IA32_EMULATION) := ia32entry.o sys_ia32.o ia32_ioctl.o \
ia32_signal.o \
ia32_binfmt.o fpu32.o socket32.o ptrace32.o ipc32.o syscall32.o
ia32_binfmt.o fpu32.o ptrace32.o ipc32.o syscall32.o
......@@ -302,7 +302,7 @@ ia32_sys_call_table:
.quad compat_sys_statfs
.quad compat_sys_fstatfs /* 100 */
.quad sys_ioperm
.quad sys32_socketcall
.quad compat_sys_socketcall
.quad sys_syslog
.quad compat_sys_setitimer
.quad compat_sys_getitimer /* 105 */
......
......@@ -738,7 +738,7 @@ asmlinkage ssize_t sys_readv(unsigned long,const struct iovec *,unsigned long);
asmlinkage ssize_t sys_writev(unsigned long,const struct iovec *,unsigned long);
static struct iovec *
get_iovec32(struct iovec32 *iov32, struct iovec *iov_buf, u32 count, int type, int *errp)
get_compat_iovec(struct compat_iovec *iov32, struct iovec *iov_buf, u32 count, int type, int *errp)
{
int i;
u32 buf, len;
......@@ -751,7 +751,7 @@ get_iovec32(struct iovec32 *iov32, struct iovec *iov_buf, u32 count, int type, i
return 0;
if (count > UIO_MAXIOV)
return(struct iovec *)0;
if(verify_area(VERIFY_READ, iov32, sizeof(struct iovec32)*count))
if(verify_area(VERIFY_READ, iov32, sizeof(struct compat_iovec)*count))
return(struct iovec *)0;
if (count > UIO_FASTIOV) {
*errp = -ENOMEM;
......@@ -792,14 +792,14 @@ get_iovec32(struct iovec32 *iov32, struct iovec *iov_buf, u32 count, int type, i
}
asmlinkage long
sys32_readv(int fd, struct iovec32 *vector, u32 count)
sys32_readv(int fd, struct compat_iovec *vector, u32 count)
{
struct iovec iovstack[UIO_FASTIOV];
struct iovec *iov;
int ret;
mm_segment_t old_fs = get_fs();
if ((iov = get_iovec32(vector, iovstack, count, VERIFY_WRITE, &ret)) == NULL)
if ((iov = get_compat_iovec(vector, iovstack, count, VERIFY_WRITE, &ret)) == NULL)
return ret;
set_fs(KERNEL_DS);
ret = sys_readv(fd, iov, count);
......@@ -810,14 +810,14 @@ sys32_readv(int fd, struct iovec32 *vector, u32 count)
}
asmlinkage long
sys32_writev(int fd, struct iovec32 *vector, u32 count)
sys32_writev(int fd, struct compat_iovec *vector, u32 count)
{
struct iovec iovstack[UIO_FASTIOV];
struct iovec *iov;
int ret;
mm_segment_t old_fs = get_fs();
if ((iov = get_iovec32(vector, iovstack, count, VERIFY_READ, &ret)) == NULL)
if ((iov = get_compat_iovec(vector, iovstack, count, VERIFY_READ, &ret)) == NULL)
return ret;
set_fs(KERNEL_DS);
ret = sys_writev(fd, iov, count);
......
......@@ -777,7 +777,7 @@ int pppoe_ioctl(struct socket *sock, unsigned int cmd,
int pppoe_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
int total_len, struct scm_cookie *scm)
int total_len)
{
struct sk_buff *skb = NULL;
struct sock *sk = sock->sk;
......@@ -937,7 +937,8 @@ int pppoe_xmit(struct ppp_channel *chan, struct sk_buff *skb)
struct ppp_channel_ops pppoe_chan_ops = { pppoe_xmit , NULL };
int pppoe_rcvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, int total_len, int flags, struct scm_cookie *scm)
int pppoe_recvmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *m, int total_len, int flags)
{
struct sock *sk = sock->sk;
struct sk_buff *skb = NULL;
......@@ -1089,7 +1090,7 @@ struct proto_ops pppoe_ops = {
.setsockopt = sock_no_setsockopt,
.getsockopt = sock_no_getsockopt,
.sendmsg = pppoe_sendmsg,
.recvmsg = pppoe_rcvmsg,
.recvmsg = pppoe_recvmsg,
.mmap = sock_no_mmap
};
......
......@@ -41,8 +41,6 @@ _recvfrom(struct socket *socket, unsigned char *ubuf, int size, unsigned flags)
{
struct iovec iov;
struct msghdr msg;
struct kiocb iocb;
struct sock_iocb *si;
mm_segment_t fs;
fs = get_fs();
......@@ -58,21 +56,7 @@ _recvfrom(struct socket *socket, unsigned char *ubuf, int size, unsigned flags)
iov.iov_base = ubuf;
iov.iov_len = size;
init_sync_kiocb(&iocb, NULL);
si = kiocb_to_siocb(&iocb);
si->sock = socket;
si->scm = &si->async_scm;
si->msg = &msg;
si->size = size;
si->flags = flags;
memset(si->scm, 0, sizeof(*si->scm));
size = socket->ops->recvmsg(&iocb, socket, &msg, size, flags, si->scm);
if (size >= 0)
scm_recv(socket, &msg, si->scm, flags);
if (-EIOCBQUEUED == size)
size = wait_on_sync_kiocb(&iocb);
size = sock_recvmsg(socket, &msg, size, flags);
set_fs(fs);
return size;
......@@ -299,8 +283,6 @@ smb_receive_drop(struct smb_sb_info *server)
unsigned int flags;
struct iovec iov;
struct msghdr msg;
struct kiocb iocb;
struct sock_iocb *si;
mm_segment_t fs;
int rlen = smb_len(server->header) - server->smb_read + 4;
int result = -EIO;
......@@ -327,21 +309,7 @@ smb_receive_drop(struct smb_sb_info *server)
if (rlen > PAGE_SIZE)
rlen = PAGE_SIZE;
init_sync_kiocb(&iocb, NULL);
si = kiocb_to_siocb(&iocb);
si->sock = sock;
si->scm = &si->async_scm;
si->msg = &msg;
si->size = rlen;
si->flags = flags;
memset(si->scm, 0, sizeof(*si->scm));
result = sock->ops->recvmsg(&iocb, sock, &msg, rlen, flags, si->scm);
if (result >= 0)
scm_recv(sock, &msg, si->scm, flags);
if (-EIOCBQUEUED == result)
result = wait_on_sync_kiocb(&iocb);
result = sock_recvmsg(sock, &msg, rlen, flags);
set_fs(fs);
......@@ -370,8 +338,6 @@ smb_receive(struct smb_sb_info *server, struct smb_request *req)
unsigned int flags;
struct iovec iov[4];
struct msghdr msg;
struct kiocb iocb;
struct sock_iocb *si;
mm_segment_t fs;
int rlen;
int result = -EIO;
......@@ -398,21 +364,7 @@ smb_receive(struct smb_sb_info *server, struct smb_request *req)
if (req->rq_rlen < rlen)
rlen = req->rq_rlen;
init_sync_kiocb(&iocb, NULL);
si = kiocb_to_siocb(&iocb);
si->sock = sock;
si->scm = &si->async_scm;
si->msg = &msg;
si->size = rlen;
si->flags = flags;
memset(si->scm, 0, sizeof(*si->scm));
result = sock->ops->recvmsg(&iocb, sock, &msg, rlen, flags, si->scm);
if (result >= 0)
scm_recv(sock, &msg, si->scm, flags);
if (-EIOCBQUEUED == result)
result = wait_on_sync_kiocb(&iocb);
result = sock_recvmsg(sock, &msg, rlen, flags);
set_fs(fs);
......@@ -440,8 +392,6 @@ smb_send_request(struct smb_request *req)
mm_segment_t fs;
struct smb_sb_info *server = req->rq_server;
struct socket *sock;
struct kiocb iocb;
struct sock_iocb *si;
struct msghdr msg;
int slen = req->rq_slen - req->rq_bytes_sent;
int result = -EIO;
......@@ -465,23 +415,9 @@ smb_send_request(struct smb_request *req)
if (req->rq_bytes_sent)
smb_move_iov(&msg, iov, req->rq_bytes_sent);
init_sync_kiocb(&iocb, NULL);
si = kiocb_to_siocb(&iocb);
si->scm = &si->async_scm;
si->sock = sock;
si->msg = &msg;
si->size = slen;
fs = get_fs();
set_fs(get_ds());
result = scm_send(sock, &msg, si->scm);
if (result >= 0) {
result = sock->ops->sendmsg(&iocb, sock, &msg, slen, si->scm);
if (-EIOCBQUEUED != result)
scm_destroy(si->scm);
}
if (-EIOCBQUEUED == result)
result = wait_on_sync_kiocb(&iocb);
result = sock_sendmsg(sock, &msg, slen);
set_fs(fs);
if (result >= 0) {
......
......@@ -153,11 +153,6 @@ struct ustat32 {
char f_fpack[6];
};
struct iovec32 {
unsigned int iov_base;
int iov_len;
};
#define IA32_PAGE_OFFSET 0xffffe000
#define IA32_STACK_TOP IA32_PAGE_OFFSET
......
#ifndef SOCKET32_H
#define SOCKET32_H 1
#include <linux/compat.h>
/* XXX This really belongs in some header file... -DaveM */
#define MAX_SOCK_ADDR 128 /* 108 for Unix domain -
16 for IP, 16 for IPX,
24 for IPv6,
about 80 for AX.25 */
struct msghdr32 {
u32 msg_name;
int msg_namelen;
u32 msg_iov;
compat_size_t msg_iovlen;
u32 msg_control;
compat_size_t msg_controllen;
unsigned msg_flags;
};
struct cmsghdr32 {
compat_size_t cmsg_len;
int cmsg_level;
int cmsg_type;
};
/* Bleech... */
#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen))
#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen))
#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) )
#define CMSG32_DATA(cmsg) ((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32))))
#define CMSG32_SPACE(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len))
#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len))
#define __CMSG32_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr32) ? \
(struct cmsghdr32 *)(ctl) : \
(struct cmsghdr32 *)NULL)
#define CMSG32_FIRSTHDR(msg) __CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
__inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size,
struct cmsghdr32 *__cmsg, int __cmsg_len)
{
struct cmsghdr32 * __ptr;
__ptr = (struct cmsghdr32 *)(((unsigned char *) __cmsg) +
CMSG32_ALIGN(__cmsg_len));
if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size)
return NULL;
return __ptr;
}
__inline__ struct cmsghdr32 *cmsg32_nxthdr (struct msghdr *__msg,
struct cmsghdr32 *__cmsg,
int __cmsg_len)
{
return __cmsg32_nxthdr(__msg->msg_control, __msg->msg_controllen,
__cmsg, __cmsg_len);
}
#endif
......@@ -45,5 +45,12 @@ extern int put_compat_flock(struct flock *, struct compat_flock *);
extern int get_compat_timespec(struct timespec *, struct compat_timespec *);
extern int put_compat_timespec(struct timespec *, struct compat_timespec *);
struct compat_iovec {
u32 iov_base;
compat_size_t iov_len;
};
#else /* no CONFIG_COMPAT */
#define compat_size_t size_t
#endif /* CONFIG_COMPAT */
#endif /* _LINUX_COMPAT_H */
......@@ -78,7 +78,6 @@ struct socket
unsigned char passcred;
};
struct scm_cookie;
struct vm_area_struct;
struct page;
struct kiocb;
......@@ -106,11 +105,9 @@ struct proto_ops {
int (*getsockopt) (struct socket *sock, int level, int optname,
char *optval, int *optlen);
int (*sendmsg) (struct kiocb *iocb, struct socket *sock,
struct msghdr *m, int total_len,
struct scm_cookie *scm);
struct msghdr *m, int total_len);
int (*recvmsg) (struct kiocb *iocb, struct socket *sock,
struct msghdr *m, int total_len, int flags,
struct scm_cookie *scm);
struct msghdr *m, int total_len, int flags);
int (*mmap) (struct file *file, struct socket *sock, struct vm_area_struct * vma);
ssize_t (*sendpage) (struct socket *sock, struct page *page, int offset, size_t size, int flags);
};
......@@ -202,10 +199,10 @@ SOCKCALL_WRAP(name, setsockopt, (struct socket *sock, int level, int optname, \
char *optval, int optlen), (sock, level, optname, optval, optlen)) \
SOCKCALL_WRAP(name, getsockopt, (struct socket *sock, int level, int optname, \
char *optval, int *optlen), (sock, level, optname, optval, optlen)) \
SOCKCALL_WRAP(name, sendmsg, (struct kiocb *iocb, struct socket *sock, struct msghdr *m, int len, struct scm_cookie *scm), \
(iocb, sock, m, len, scm)) \
SOCKCALL_WRAP(name, recvmsg, (struct kiocb *iocb, struct socket *sock, struct msghdr *m, int len, int flags, struct scm_cookie *scm), \
(iocb, sock, m, len, flags, scm)) \
SOCKCALL_WRAP(name, sendmsg, (struct kiocb *iocb, struct socket *sock, struct msghdr *m, int len), \
(iocb, sock, m, len)) \
SOCKCALL_WRAP(name, recvmsg, (struct kiocb *iocb, struct socket *sock, struct msghdr *m, int len, int flags), \
(iocb, sock, m, len, flags)) \
SOCKCALL_WRAP(name, mmap, (struct file *file, struct socket *sock, struct vm_area_struct *vma), \
(file, sock, vma)) \
\
......
......@@ -3,6 +3,7 @@
#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
#include <linux/linkage.h>
#include <asm/socket.h> /* arch-dependent defines */
#include <linux/sockios.h> /* the SIOCxxx I/O controls */
#include <linux/uio.h> /* iovec support */
......@@ -234,6 +235,24 @@ struct ucred {
#define MSG_EOF MSG_FIN
#if defined(CONFIG_COMPAT)
#define MSG_CMSG_COMPAT 0x80000000 /* This message needs 32 bit fixups */
#else
#define MSG_CMSG_COMPAT 0 /* We never have 32 bit fixups */
#define compat_msghdr msghdr /* Needed to avoid compiler hoops */
#endif
struct compat_msghdr;
extern int msghdr_from_user_compat_to_kern(struct msghdr *, struct compat_msghdr *);
extern int verify_compat_iovec(struct msghdr *, struct iovec *, char *, int);
extern asmlinkage long compat_sys_sendmsg(int,struct compat_msghdr *,unsigned);
extern asmlinkage long compat_sys_recvmsg(int,struct compat_msghdr *,unsigned);
extern asmlinkage long sys_sendmsg(int fd, struct msghdr *msg, unsigned flags);
extern asmlinkage long sys_recvmsg(int fd, struct msghdr *msg, unsigned flags);
extern asmlinkage long compat_sys_getsockopt(int fd, int level, int optname,
char *optval, int *optlen);
/* Setsockoptions(2) level. Thanks to BSD these must match IPPROTO_xxx */
#define SOL_IP 0
......@@ -276,6 +295,11 @@ extern void memcpy_tokerneliovec(struct iovec *iov, unsigned char *kdata, int le
extern int move_addr_to_user(void *kaddr, int klen, void *uaddr, int *ulen);
extern int move_addr_to_kernel(void *uaddr, int ulen, void *kaddr);
extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data);
extern int put_cmsg_compat(struct msghdr*, int level, int type, int len, void *data);
extern void cmsg_compat_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr);
extern int cmsghdr_from_user_compat_to_kern(struct msghdr *kmsg,
unsigned char *stackbuf, int stackbuf_size);
#endif
#endif /* not kernel and not glibc */
#endif /* _LINUX_SOCKET_H */
......@@ -128,7 +128,7 @@ int bt_sock_unregister(int proto);
struct sock *bt_sock_alloc(struct socket *sock, int proto, int pi_size, int prio);
void bt_sock_link(struct bt_sock_list *l, struct sock *s);
void bt_sock_unlink(struct bt_sock_list *l, struct sock *s);
int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int len, int flags, struct scm_cookie *scm);
int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int len, int flags);
uint bt_sock_poll(struct file * file, struct socket *sock, poll_table *wait);
int bt_sock_w4_connect(struct sock *sk, int flags);
......
This diff is collapsed.
......@@ -23,11 +23,11 @@ extern int inet_accept(struct socket *sock,
extern int inet_recvmsg(struct kiocb *iocb,
struct socket *sock,
struct msghdr *ubuf,
int size, int flags, struct scm_cookie *scm);
int size, int flags);
extern int inet_sendmsg(struct kiocb *iocb,
struct socket *sock,
struct msghdr *msg,
int size, struct scm_cookie *scm);
int size);
extern int inet_shutdown(struct socket *sock, int how);
extern unsigned int inet_poll(struct file * file, struct socket *sock, struct poll_table_struct *wait);
extern int inet_setsockopt(struct socket *sock, int level,
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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