Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
675a53bd
Commit
675a53bd
authored
Nov 21, 2014
by
David S. Miller
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'for-davem' of
git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
parents
abd40774
232365f6
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
114 additions
and
211 deletions
+114
-211
arch/arm/kernel/sys_oabi-compat.c
arch/arm/kernel/sys_oabi-compat.c
+2
-2
include/linux/socket.h
include/linux/socket.h
+13
-4
include/linux/syscalls.h
include/linux/syscalls.h
+3
-3
include/net/compat.h
include/net/compat.h
+2
-3
include/net/sock.h
include/net/sock.h
+0
-23
net/compat.c
net/compat.c
+27
-56
net/core/iovec.c
net/core/iovec.c
+0
-47
net/socket.c
net/socket.c
+67
-73
No files found.
arch/arm/kernel/sys_oabi-compat.c
View file @
675a53bd
...
...
@@ -400,7 +400,7 @@ asmlinkage long sys_oabi_sendto(int fd, void __user *buff,
return
sys_sendto
(
fd
,
buff
,
len
,
flags
,
addr
,
addrlen
);
}
asmlinkage
long
sys_oabi_sendmsg
(
int
fd
,
struct
msghdr
__user
*
msg
,
unsigned
flags
)
asmlinkage
long
sys_oabi_sendmsg
(
int
fd
,
struct
user_
msghdr
__user
*
msg
,
unsigned
flags
)
{
struct
sockaddr
__user
*
addr
;
int
msg_namelen
;
...
...
@@ -446,7 +446,7 @@ asmlinkage long sys_oabi_socketcall(int call, unsigned long __user *args)
break
;
case
SYS_SENDMSG
:
if
(
copy_from_user
(
a
,
args
,
3
*
sizeof
(
long
))
==
0
)
r
=
sys_oabi_sendmsg
(
a
[
0
],
(
struct
msghdr
__user
*
)
a
[
1
],
a
[
2
]);
r
=
sys_oabi_sendmsg
(
a
[
0
],
(
struct
user_
msghdr
__user
*
)
a
[
1
],
a
[
2
]);
break
;
default:
r
=
sys_socketcall
(
call
,
args
);
...
...
include/linux/socket.h
View file @
675a53bd
...
...
@@ -54,9 +54,19 @@ struct msghdr {
unsigned
int
msg_flags
;
/* flags on received message */
};
struct
user_msghdr
{
void
__user
*
msg_name
;
/* ptr to socket address structure */
int
msg_namelen
;
/* size of socket address structure */
struct
iovec
__user
*
msg_iov
;
/* scatter/gather array */
__kernel_size_t
msg_iovlen
;
/* # elements in msg_iov */
void
__user
*
msg_control
;
/* ancillary data */
__kernel_size_t
msg_controllen
;
/* ancillary data buffer length */
unsigned
int
msg_flags
;
/* flags on received message */
};
/* For recvmmsg/sendmmsg */
struct
mmsghdr
{
struct
msghdr
msg_hdr
;
struct
user_msghdr
msg_hdr
;
unsigned
int
msg_len
;
};
...
...
@@ -312,15 +322,14 @@ extern int csum_partial_copy_fromiovecend(unsigned char *kdata,
extern
unsigned
long
iov_pages
(
const
struct
iovec
*
iov
,
int
offset
,
unsigned
long
nr_segs
);
extern
int
verify_iovec
(
struct
msghdr
*
m
,
struct
iovec
*
iov
,
struct
sockaddr_storage
*
address
,
int
mode
);
extern
int
move_addr_to_kernel
(
void
__user
*
uaddr
,
int
ulen
,
struct
sockaddr_storage
*
kaddr
);
extern
int
put_cmsg
(
struct
msghdr
*
,
int
level
,
int
type
,
int
len
,
void
*
data
);
struct
timespec
;
/* The __sys_...msg variants allow MSG_CMSG_COMPAT */
extern
long
__sys_recvmsg
(
int
fd
,
struct
msghdr
__user
*
msg
,
unsigned
flags
);
extern
long
__sys_sendmsg
(
int
fd
,
struct
msghdr
__user
*
msg
,
unsigned
flags
);
extern
long
__sys_recvmsg
(
int
fd
,
struct
user_
msghdr
__user
*
msg
,
unsigned
flags
);
extern
long
__sys_sendmsg
(
int
fd
,
struct
user_
msghdr
__user
*
msg
,
unsigned
flags
);
extern
int
__sys_recvmmsg
(
int
fd
,
struct
mmsghdr
__user
*
mmsg
,
unsigned
int
vlen
,
unsigned
int
flags
,
struct
timespec
*
timeout
);
extern
int
__sys_sendmmsg
(
int
fd
,
struct
mmsghdr
__user
*
mmsg
,
...
...
include/linux/syscalls.h
View file @
675a53bd
...
...
@@ -25,7 +25,7 @@ struct linux_dirent64;
struct
list_head
;
struct
mmap_arg_struct
;
struct
msgbuf
;
struct
msghdr
;
struct
user_
msghdr
;
struct
mmsghdr
;
struct
msqid_ds
;
struct
new_utsname
;
...
...
@@ -601,13 +601,13 @@ asmlinkage long sys_getpeername(int, struct sockaddr __user *, int __user *);
asmlinkage
long
sys_send
(
int
,
void
__user
*
,
size_t
,
unsigned
);
asmlinkage
long
sys_sendto
(
int
,
void
__user
*
,
size_t
,
unsigned
,
struct
sockaddr
__user
*
,
int
);
asmlinkage
long
sys_sendmsg
(
int
fd
,
struct
msghdr
__user
*
msg
,
unsigned
flags
);
asmlinkage
long
sys_sendmsg
(
int
fd
,
struct
user_
msghdr
__user
*
msg
,
unsigned
flags
);
asmlinkage
long
sys_sendmmsg
(
int
fd
,
struct
mmsghdr
__user
*
msg
,
unsigned
int
vlen
,
unsigned
flags
);
asmlinkage
long
sys_recv
(
int
,
void
__user
*
,
size_t
,
unsigned
);
asmlinkage
long
sys_recvfrom
(
int
,
void
__user
*
,
size_t
,
unsigned
,
struct
sockaddr
__user
*
,
int
__user
*
);
asmlinkage
long
sys_recvmsg
(
int
fd
,
struct
msghdr
__user
*
msg
,
unsigned
flags
);
asmlinkage
long
sys_recvmsg
(
int
fd
,
struct
user_
msghdr
__user
*
msg
,
unsigned
flags
);
asmlinkage
long
sys_recvmmsg
(
int
fd
,
struct
mmsghdr
__user
*
msg
,
unsigned
int
vlen
,
unsigned
flags
,
struct
timespec
__user
*
timeout
);
...
...
include/net/compat.h
View file @
675a53bd
...
...
@@ -40,9 +40,8 @@ int compat_sock_get_timestampns(struct sock *, struct timespec __user *);
#define compat_mmsghdr mmsghdr
#endif
/* defined(CONFIG_COMPAT) */
int
get_compat_msghdr
(
struct
msghdr
*
,
struct
compat_msghdr
__user
*
);
int
verify_compat_iovec
(
struct
msghdr
*
,
struct
iovec
*
,
struct
sockaddr_storage
*
,
int
);
ssize_t
get_compat_msghdr
(
struct
msghdr
*
,
struct
compat_msghdr
__user
*
,
struct
sockaddr
__user
**
,
struct
iovec
**
);
asmlinkage
long
compat_sys_sendmsg
(
int
,
struct
compat_msghdr
__user
*
,
unsigned
int
);
asmlinkage
long
compat_sys_sendmmsg
(
int
,
struct
compat_mmsghdr
__user
*
,
...
...
include/net/sock.h
View file @
675a53bd
...
...
@@ -1884,29 +1884,6 @@ static inline int skb_copy_to_page_nocache(struct sock *sk, char __user *from,
return
0
;
}
static
inline
int
skb_copy_to_page
(
struct
sock
*
sk
,
char
__user
*
from
,
struct
sk_buff
*
skb
,
struct
page
*
page
,
int
off
,
int
copy
)
{
if
(
skb
->
ip_summed
==
CHECKSUM_NONE
)
{
int
err
=
0
;
__wsum
csum
=
csum_and_copy_from_user
(
from
,
page_address
(
page
)
+
off
,
copy
,
0
,
&
err
);
if
(
err
)
return
err
;
skb
->
csum
=
csum_block_add
(
skb
->
csum
,
csum
,
skb
->
len
);
}
else
if
(
copy_from_user
(
page_address
(
page
)
+
off
,
from
,
copy
))
return
-
EFAULT
;
skb
->
len
+=
copy
;
skb
->
data_len
+=
copy
;
skb
->
truesize
+=
copy
;
sk
->
sk_wmem_queued
+=
copy
;
sk_mem_charge
(
sk
,
copy
);
return
0
;
}
/**
* sk_wmem_alloc_get - returns write allocations
* @sk: socket
...
...
net/compat.c
View file @
675a53bd
...
...
@@ -31,41 +31,18 @@
#include <asm/uaccess.h>
#include <net/compat.h>
static
inline
int
iov_from_user_compat_to_kern
(
struct
iovec
*
kiov
,
struct
compat_iovec
__user
*
uiov32
,
int
niov
)
ssize_t
get_compat_msghdr
(
struct
msghdr
*
kmsg
,
struct
compat_msghdr
__user
*
umsg
,
struct
sockaddr
__user
**
save_addr
,
struct
iovec
**
iov
)
{
int
tot_len
=
0
;
while
(
niov
>
0
)
{
compat_uptr_t
buf
;
compat_size_t
len
;
if
(
get_user
(
len
,
&
uiov32
->
iov_len
)
||
get_user
(
buf
,
&
uiov32
->
iov_base
))
return
-
EFAULT
;
if
(
len
>
INT_MAX
-
tot_len
)
len
=
INT_MAX
-
tot_len
;
tot_len
+=
len
;
kiov
->
iov_base
=
compat_ptr
(
buf
);
kiov
->
iov_len
=
(
__kernel_size_t
)
len
;
uiov32
++
;
kiov
++
;
niov
--
;
}
return
tot_len
;
}
int
get_compat_msghdr
(
struct
msghdr
*
kmsg
,
struct
compat_msghdr
__user
*
umsg
)
{
compat_uptr_t
tmp1
,
tmp2
,
tmp3
;
compat_uptr_t
uaddr
,
uiov
,
tmp3
;
ssize_t
err
;
if
(
!
access_ok
(
VERIFY_READ
,
umsg
,
sizeof
(
*
umsg
))
||
__get_user
(
tmp1
,
&
umsg
->
msg_name
)
||
__get_user
(
uaddr
,
&
umsg
->
msg_name
)
||
__get_user
(
kmsg
->
msg_namelen
,
&
umsg
->
msg_namelen
)
||
__get_user
(
tmp2
,
&
umsg
->
msg_iov
)
||
__get_user
(
uiov
,
&
umsg
->
msg_iov
)
||
__get_user
(
kmsg
->
msg_iovlen
,
&
umsg
->
msg_iovlen
)
||
__get_user
(
tmp3
,
&
umsg
->
msg_control
)
||
__get_user
(
kmsg
->
msg_controllen
,
&
umsg
->
msg_controllen
)
||
...
...
@@ -73,39 +50,33 @@ int get_compat_msghdr(struct msghdr *kmsg, struct compat_msghdr __user *umsg)
return
-
EFAULT
;
if
(
kmsg
->
msg_namelen
>
sizeof
(
struct
sockaddr_storage
))
kmsg
->
msg_namelen
=
sizeof
(
struct
sockaddr_storage
);
kmsg
->
msg_name
=
compat_ptr
(
tmp1
);
kmsg
->
msg_iov
=
compat_ptr
(
tmp2
);
kmsg
->
msg_control
=
compat_ptr
(
tmp3
);
return
0
;
}
/* I've named the args so it is easy to tell whose space the pointers are in. */
int
verify_compat_iovec
(
struct
msghdr
*
kern_msg
,
struct
iovec
*
kern_iov
,
struct
sockaddr_storage
*
kern_address
,
int
mode
)
{
int
tot_len
;
if
(
save_addr
)
*
save_addr
=
compat_ptr
(
uaddr
);
if
(
kern_msg
->
msg_name
&&
kern_
msg
->
msg_namelen
)
{
if
(
mode
==
VERIFY_READ
)
{
int
err
=
move_addr_to_kernel
(
kern_msg
->
msg_name
,
kern_
msg
->
msg_namelen
,
kern_address
);
if
(
uaddr
&&
k
msg
->
msg_namelen
)
{
if
(
!
save_addr
)
{
err
=
move_addr_to_kernel
(
compat_ptr
(
uaddr
)
,
k
msg
->
msg_namelen
,
kmsg
->
msg_name
);
if
(
err
<
0
)
return
err
;
}
kern_msg
->
msg_name
=
kern_address
;
}
else
{
k
ern_
msg
->
msg_name
=
NULL
;
k
ern_
msg
->
msg_namelen
=
0
;
kmsg
->
msg_name
=
NULL
;
kmsg
->
msg_namelen
=
0
;
}
tot_len
=
iov_from_user_compat_to_kern
(
kern_iov
,
(
struct
compat_iovec
__user
*
)
kern_msg
->
msg_iov
,
kern_msg
->
msg_iovlen
);
if
(
tot_len
>=
0
)
kern_msg
->
msg_iov
=
kern_iov
;
if
(
kmsg
->
msg_iovlen
>
UIO_MAXIOV
)
return
-
EMSGSIZE
;
return
tot_len
;
err
=
compat_rw_copy_check_uvector
(
save_addr
?
READ
:
WRITE
,
compat_ptr
(
uiov
),
kmsg
->
msg_iovlen
,
UIO_FASTIOV
,
*
iov
,
iov
);
if
(
err
>=
0
)
kmsg
->
msg_iov
=
*
iov
;
return
err
;
}
/* Bleech... */
...
...
@@ -740,7 +711,7 @@ COMPAT_SYSCALL_DEFINE3(sendmsg, int, fd, struct compat_msghdr __user *, msg, uns
{
if
(
flags
&
MSG_CMSG_COMPAT
)
return
-
EINVAL
;
return
__sys_sendmsg
(
fd
,
(
struct
msghdr
__user
*
)
msg
,
flags
|
MSG_CMSG_COMPAT
);
return
__sys_sendmsg
(
fd
,
(
struct
user_
msghdr
__user
*
)
msg
,
flags
|
MSG_CMSG_COMPAT
);
}
COMPAT_SYSCALL_DEFINE4
(
sendmmsg
,
int
,
fd
,
struct
compat_mmsghdr
__user
*
,
mmsg
,
...
...
@@ -756,7 +727,7 @@ COMPAT_SYSCALL_DEFINE3(recvmsg, int, fd, struct compat_msghdr __user *, msg, uns
{
if
(
flags
&
MSG_CMSG_COMPAT
)
return
-
EINVAL
;
return
__sys_recvmsg
(
fd
,
(
struct
msghdr
__user
*
)
msg
,
flags
|
MSG_CMSG_COMPAT
);
return
__sys_recvmsg
(
fd
,
(
struct
user_
msghdr
__user
*
)
msg
,
flags
|
MSG_CMSG_COMPAT
);
}
COMPAT_SYSCALL_DEFINE4
(
recv
,
int
,
fd
,
void
__user
*
,
buf
,
compat_size_t
,
len
,
unsigned
int
,
flags
)
...
...
net/core/iovec.c
View file @
675a53bd
...
...
@@ -27,53 +27,6 @@
#include <net/checksum.h>
#include <net/sock.h>
/*
* Verify iovec. The caller must ensure that the iovec is big enough
* to hold the message iovec.
*
* Save time not doing access_ok. copy_*_user will make this work
* in any case.
*/
int
verify_iovec
(
struct
msghdr
*
m
,
struct
iovec
*
iov
,
struct
sockaddr_storage
*
address
,
int
mode
)
{
int
size
,
ct
,
err
;
if
(
m
->
msg_name
&&
m
->
msg_namelen
)
{
if
(
mode
==
VERIFY_READ
)
{
void
__user
*
namep
;
namep
=
(
void
__user
__force
*
)
m
->
msg_name
;
err
=
move_addr_to_kernel
(
namep
,
m
->
msg_namelen
,
address
);
if
(
err
<
0
)
return
err
;
}
m
->
msg_name
=
address
;
}
else
{
m
->
msg_name
=
NULL
;
m
->
msg_namelen
=
0
;
}
size
=
m
->
msg_iovlen
*
sizeof
(
struct
iovec
);
if
(
copy_from_user
(
iov
,
(
void
__user
__force
*
)
m
->
msg_iov
,
size
))
return
-
EFAULT
;
m
->
msg_iov
=
iov
;
err
=
0
;
for
(
ct
=
0
;
ct
<
m
->
msg_iovlen
;
ct
++
)
{
size_t
len
=
iov
[
ct
].
iov_len
;
if
(
len
>
INT_MAX
-
err
)
{
len
=
INT_MAX
-
err
;
iov
[
ct
].
iov_len
=
len
;
}
err
+=
len
;
}
return
err
;
}
/*
* And now for the all-in-one: copy and checksum from a user iovec
* directly to a datagram
...
...
net/socket.c
View file @
675a53bd
...
...
@@ -1988,13 +1988,26 @@ struct used_address {
unsigned
int
name_len
;
};
static
int
copy_msghdr_from_user
(
struct
msghdr
*
kmsg
,
struct
msghdr
__user
*
umsg
)
static
ssize_t
copy_msghdr_from_user
(
struct
msghdr
*
kmsg
,
struct
user_msghdr
__user
*
umsg
,
struct
sockaddr
__user
**
save_addr
,
struct
iovec
**
iov
)
{
if
(
copy_from_user
(
kmsg
,
umsg
,
sizeof
(
struct
msghdr
)))
struct
sockaddr
__user
*
uaddr
;
struct
iovec
__user
*
uiov
;
ssize_t
err
;
if
(
!
access_ok
(
VERIFY_READ
,
umsg
,
sizeof
(
*
umsg
))
||
__get_user
(
uaddr
,
&
umsg
->
msg_name
)
||
__get_user
(
kmsg
->
msg_namelen
,
&
umsg
->
msg_namelen
)
||
__get_user
(
uiov
,
&
umsg
->
msg_iov
)
||
__get_user
(
kmsg
->
msg_iovlen
,
&
umsg
->
msg_iovlen
)
||
__get_user
(
kmsg
->
msg_control
,
&
umsg
->
msg_control
)
||
__get_user
(
kmsg
->
msg_controllen
,
&
umsg
->
msg_controllen
)
||
__get_user
(
kmsg
->
msg_flags
,
&
umsg
->
msg_flags
))
return
-
EFAULT
;
if
(
kmsg
->
msg_name
==
NULL
)
if
(
!
uaddr
)
kmsg
->
msg_namelen
=
0
;
if
(
kmsg
->
msg_namelen
<
0
)
...
...
@@ -2002,10 +2015,34 @@ static int copy_msghdr_from_user(struct msghdr *kmsg,
if
(
kmsg
->
msg_namelen
>
sizeof
(
struct
sockaddr_storage
))
kmsg
->
msg_namelen
=
sizeof
(
struct
sockaddr_storage
);
return
0
;
if
(
save_addr
)
*
save_addr
=
uaddr
;
if
(
uaddr
&&
kmsg
->
msg_namelen
)
{
if
(
!
save_addr
)
{
err
=
move_addr_to_kernel
(
uaddr
,
kmsg
->
msg_namelen
,
kmsg
->
msg_name
);
if
(
err
<
0
)
return
err
;
}
}
else
{
kmsg
->
msg_name
=
NULL
;
kmsg
->
msg_namelen
=
0
;
}
if
(
kmsg
->
msg_iovlen
>
UIO_MAXIOV
)
return
-
EMSGSIZE
;
err
=
rw_copy_check_uvector
(
save_addr
?
READ
:
WRITE
,
uiov
,
kmsg
->
msg_iovlen
,
UIO_FASTIOV
,
*
iov
,
iov
);
if
(
err
>=
0
)
kmsg
->
msg_iov
=
*
iov
;
return
err
;
}
static
int
___sys_sendmsg
(
struct
socket
*
sock
,
struct
msghdr
__user
*
msg
,
static
int
___sys_sendmsg
(
struct
socket
*
sock
,
struct
user_
msghdr
__user
*
msg
,
struct
msghdr
*
msg_sys
,
unsigned
int
flags
,
struct
used_address
*
used_address
)
{
...
...
@@ -2017,34 +2054,15 @@ static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
__attribute__
((
aligned
(
sizeof
(
__kernel_size_t
))));
/* 20 is size of ipv6_pktinfo */
unsigned
char
*
ctl_buf
=
ctl
;
int
err
,
ctl_len
,
total_len
;
int
ctl_len
,
total_len
;
ssize_t
err
;
err
=
-
EFAULT
;
if
(
MSG_CMSG_COMPAT
&
flags
)
{
if
(
get_compat_msghdr
(
msg_sys
,
msg_compat
))
return
-
EFAULT
;
}
else
{
err
=
copy_msghdr_from_user
(
msg_sys
,
msg
);
if
(
err
)
return
err
;
}
msg_sys
->
msg_name
=
&
address
;
if
(
msg_sys
->
msg_iovlen
>
UIO_FASTIOV
)
{
err
=
-
EMSGSIZE
;
if
(
msg_sys
->
msg_iovlen
>
UIO_MAXIOV
)
goto
out
;
err
=
-
ENOMEM
;
iov
=
kmalloc
(
msg_sys
->
msg_iovlen
*
sizeof
(
struct
iovec
),
GFP_KERNEL
);
if
(
!
iov
)
goto
out
;
}
/* This will also move the address data into kernel space */
if
(
MSG_CMSG_COMPAT
&
flags
)
{
err
=
verify_compat_iovec
(
msg_sys
,
iov
,
&
address
,
VERIFY_READ
);
}
else
err
=
verify_iovec
(
msg_sys
,
iov
,
&
address
,
VERIFY_READ
);
if
(
MSG_CMSG_COMPAT
&
flags
)
err
=
get_compat_msghdr
(
msg_sys
,
msg_compat
,
NULL
,
&
iov
);
else
err
=
copy_msghdr_from_user
(
msg_sys
,
msg
,
NULL
,
&
iov
);
if
(
err
<
0
)
goto
out_freeiov
;
total_len
=
err
;
...
...
@@ -2115,7 +2133,6 @@ static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
out_freeiov:
if
(
iov
!=
iovstack
)
kfree
(
iov
);
out:
return
err
;
}
...
...
@@ -2123,7 +2140,7 @@ static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
* BSD sendmsg interface
*/
long
__sys_sendmsg
(
int
fd
,
struct
msghdr
__user
*
msg
,
unsigned
flags
)
long
__sys_sendmsg
(
int
fd
,
struct
user_
msghdr
__user
*
msg
,
unsigned
flags
)
{
int
fput_needed
,
err
;
struct
msghdr
msg_sys
;
...
...
@@ -2140,7 +2157,7 @@ long __sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags)
return
err
;
}
SYSCALL_DEFINE3
(
sendmsg
,
int
,
fd
,
struct
msghdr
__user
*
,
msg
,
unsigned
int
,
flags
)
SYSCALL_DEFINE3
(
sendmsg
,
int
,
fd
,
struct
user_
msghdr
__user
*
,
msg
,
unsigned
int
,
flags
)
{
if
(
flags
&
MSG_CMSG_COMPAT
)
return
-
EINVAL
;
...
...
@@ -2177,7 +2194,7 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
while
(
datagrams
<
vlen
)
{
if
(
MSG_CMSG_COMPAT
&
flags
)
{
err
=
___sys_sendmsg
(
sock
,
(
struct
msghdr
__user
*
)
compat_entry
,
err
=
___sys_sendmsg
(
sock
,
(
struct
user_
msghdr
__user
*
)
compat_entry
,
&
msg_sys
,
flags
,
&
used_address
);
if
(
err
<
0
)
break
;
...
...
@@ -2185,7 +2202,7 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
++
compat_entry
;
}
else
{
err
=
___sys_sendmsg
(
sock
,
(
struct
msghdr
__user
*
)
entry
,
(
struct
user_
msghdr
__user
*
)
entry
,
&
msg_sys
,
flags
,
&
used_address
);
if
(
err
<
0
)
break
;
...
...
@@ -2215,7 +2232,7 @@ SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
return
__sys_sendmmsg
(
fd
,
mmsg
,
vlen
,
flags
);
}
static
int
___sys_recvmsg
(
struct
socket
*
sock
,
struct
msghdr
__user
*
msg
,
static
int
___sys_recvmsg
(
struct
socket
*
sock
,
struct
user_
msghdr
__user
*
msg
,
struct
msghdr
*
msg_sys
,
unsigned
int
flags
,
int
nosec
)
{
struct
compat_msghdr
__user
*
msg_compat
=
...
...
@@ -2223,44 +2240,22 @@ static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
struct
iovec
iovstack
[
UIO_FASTIOV
];
struct
iovec
*
iov
=
iovstack
;
unsigned
long
cmsg_ptr
;
int
err
,
total_len
,
len
;
int
total_len
,
len
;
ssize_t
err
;
/* kernel mode address */
struct
sockaddr_storage
addr
;
/* user mode address pointers */
struct
sockaddr
__user
*
uaddr
;
int
__user
*
uaddr_len
;
int
__user
*
uaddr_len
=
COMPAT_NAMELEN
(
msg
)
;
if
(
MSG_CMSG_COMPAT
&
flags
)
{
if
(
get_compat_msghdr
(
msg_sys
,
msg_compat
))
return
-
EFAULT
;
}
else
{
err
=
copy_msghdr_from_user
(
msg_sys
,
msg
);
if
(
err
)
return
err
;
}
if
(
msg_sys
->
msg_iovlen
>
UIO_FASTIOV
)
{
err
=
-
EMSGSIZE
;
if
(
msg_sys
->
msg_iovlen
>
UIO_MAXIOV
)
goto
out
;
err
=
-
ENOMEM
;
iov
=
kmalloc
(
msg_sys
->
msg_iovlen
*
sizeof
(
struct
iovec
),
GFP_KERNEL
);
if
(
!
iov
)
goto
out
;
}
msg_sys
->
msg_name
=
&
addr
;
/* Save the user-mode address (verify_iovec will change the
* kernel msghdr to use the kernel address space)
*/
uaddr
=
(
__force
void
__user
*
)
msg_sys
->
msg_name
;
uaddr_len
=
COMPAT_NAMELEN
(
msg
);
if
(
MSG_CMSG_COMPAT
&
flags
)
err
=
verify_compat_iovec
(
msg_sys
,
iov
,
&
addr
,
VERIFY_WRITE
);
err
=
get_compat_msghdr
(
msg_sys
,
msg_compat
,
&
uaddr
,
&
iov
);
else
err
=
verify_iovec
(
msg_sys
,
iov
,
&
addr
,
VERIFY_WRITE
);
err
=
copy_msghdr_from_user
(
msg_sys
,
msg
,
&
uaddr
,
&
iov
);
if
(
err
<
0
)
goto
out_freeiov
;
total_len
=
err
;
...
...
@@ -2303,7 +2298,6 @@ static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
out_freeiov:
if
(
iov
!=
iovstack
)
kfree
(
iov
);
out:
return
err
;
}
...
...
@@ -2311,7 +2305,7 @@ static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
* BSD recvmsg interface
*/
long
__sys_recvmsg
(
int
fd
,
struct
msghdr
__user
*
msg
,
unsigned
flags
)
long
__sys_recvmsg
(
int
fd
,
struct
user_
msghdr
__user
*
msg
,
unsigned
flags
)
{
int
fput_needed
,
err
;
struct
msghdr
msg_sys
;
...
...
@@ -2328,7 +2322,7 @@ long __sys_recvmsg(int fd, struct msghdr __user *msg, unsigned flags)
return
err
;
}
SYSCALL_DEFINE3
(
recvmsg
,
int
,
fd
,
struct
msghdr
__user
*
,
msg
,
SYSCALL_DEFINE3
(
recvmsg
,
int
,
fd
,
struct
user_
msghdr
__user
*
,
msg
,
unsigned
int
,
flags
)
{
if
(
flags
&
MSG_CMSG_COMPAT
)
...
...
@@ -2373,7 +2367,7 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
* No need to ask LSM for more than the first datagram.
*/
if
(
MSG_CMSG_COMPAT
&
flags
)
{
err
=
___sys_recvmsg
(
sock
,
(
struct
msghdr
__user
*
)
compat_entry
,
err
=
___sys_recvmsg
(
sock
,
(
struct
user_
msghdr
__user
*
)
compat_entry
,
&
msg_sys
,
flags
&
~
MSG_WAITFORONE
,
datagrams
);
if
(
err
<
0
)
...
...
@@ -2382,7 +2376,7 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
++
compat_entry
;
}
else
{
err
=
___sys_recvmsg
(
sock
,
(
struct
msghdr
__user
*
)
entry
,
(
struct
user_
msghdr
__user
*
)
entry
,
&
msg_sys
,
flags
&
~
MSG_WAITFORONE
,
datagrams
);
if
(
err
<
0
)
...
...
@@ -2571,13 +2565,13 @@ SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
(
int
__user
*
)
a
[
4
]);
break
;
case
SYS_SENDMSG
:
err
=
sys_sendmsg
(
a0
,
(
struct
msghdr
__user
*
)
a1
,
a
[
2
]);
err
=
sys_sendmsg
(
a0
,
(
struct
user_
msghdr
__user
*
)
a1
,
a
[
2
]);
break
;
case
SYS_SENDMMSG
:
err
=
sys_sendmmsg
(
a0
,
(
struct
mmsghdr
__user
*
)
a1
,
a
[
2
],
a
[
3
]);
break
;
case
SYS_RECVMSG
:
err
=
sys_recvmsg
(
a0
,
(
struct
msghdr
__user
*
)
a1
,
a
[
2
]);
err
=
sys_recvmsg
(
a0
,
(
struct
user_
msghdr
__user
*
)
a1
,
a
[
2
]);
break
;
case
SYS_RECVMMSG
:
err
=
sys_recvmmsg
(
a0
,
(
struct
mmsghdr
__user
*
)
a1
,
a
[
2
],
a
[
3
],
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment