net: Use standard structures for generic socket address structures.

Use sockaddr_storage{} for generic socket address storage
and ensures proper alignment.
Use sockaddr{} for pointers to omit several casts.

Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
YOSHIFUJI Hideaki 2008-07-19 22:35:47 -07:00 committed by David S. Miller
parent 53b7997fd5
commit 230b183921
5 changed files with 52 additions and 42 deletions

View file

@ -306,10 +306,10 @@ extern int csum_partial_copy_fromiovecend(unsigned char *kdata,
int offset, int offset,
unsigned int len, __wsum *csump); unsigned int len, __wsum *csump);
extern int verify_iovec(struct msghdr *m, struct iovec *iov, char *address, int mode); extern int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr *address, int mode);
extern int memcpy_toiovec(struct iovec *v, unsigned char *kdata, int len); extern int memcpy_toiovec(struct iovec *v, unsigned char *kdata, int len);
extern int move_addr_to_user(void *kaddr, int klen, void __user *uaddr, int __user *ulen); extern int move_addr_to_user(struct sockaddr *kaddr, int klen, void __user *uaddr, int __user *ulen);
extern int move_addr_to_kernel(void __user *uaddr, int ulen, void *kaddr); extern int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr *kaddr);
extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data); extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data);
#endif #endif

View file

@ -32,7 +32,7 @@ extern int compat_sock_get_timestampns(struct sock *, struct timespec __user *);
#endif /* defined(CONFIG_COMPAT) */ #endif /* defined(CONFIG_COMPAT) */
extern int get_compat_msghdr(struct msghdr *, struct compat_msghdr __user *); extern int get_compat_msghdr(struct msghdr *, struct compat_msghdr __user *);
extern int verify_compat_iovec(struct msghdr *, struct iovec *, char *, int); extern int verify_compat_iovec(struct msghdr *, struct iovec *, struct sockaddr *, int);
extern asmlinkage long compat_sys_sendmsg(int,struct compat_msghdr __user *,unsigned); extern asmlinkage long compat_sys_sendmsg(int,struct compat_msghdr __user *,unsigned);
extern asmlinkage long compat_sys_recvmsg(int,struct compat_msghdr __user *,unsigned); extern asmlinkage long compat_sys_recvmsg(int,struct compat_msghdr __user *,unsigned);
extern asmlinkage long compat_sys_getsockopt(int, int, int, char __user *, int __user *); extern asmlinkage long compat_sys_getsockopt(int, int, int, char __user *, int __user *);

View file

@ -75,7 +75,7 @@ int get_compat_msghdr(struct msghdr *kmsg, struct compat_msghdr __user *umsg)
/* I've named the args so it is easy to tell whose space the pointers are in. */ /* 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, int verify_compat_iovec(struct msghdr *kern_msg, struct iovec *kern_iov,
char *kern_address, int mode) struct sockaddr *kern_address, int mode)
{ {
int tot_len; int tot_len;

View file

@ -36,7 +36,7 @@
* in any case. * in any case.
*/ */
int verify_iovec(struct msghdr *m, struct iovec *iov, char *address, int mode) int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr *address, int mode)
{ {
int size, err, ct; int size, err, ct;

View file

@ -180,9 +180,9 @@ static DEFINE_PER_CPU(int, sockets_in_use) = 0;
* invalid addresses -EFAULT is returned. On a success 0 is returned. * invalid addresses -EFAULT is returned. On a success 0 is returned.
*/ */
int move_addr_to_kernel(void __user *uaddr, int ulen, void *kaddr) int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr *kaddr)
{ {
if (ulen < 0 || ulen > MAX_SOCK_ADDR) if (ulen < 0 || ulen > sizeof(struct sockaddr_storage))
return -EINVAL; return -EINVAL;
if (ulen == 0) if (ulen == 0)
return 0; return 0;
@ -208,7 +208,7 @@ int move_addr_to_kernel(void __user *uaddr, int ulen, void *kaddr)
* specified. Zero is returned for a success. * specified. Zero is returned for a success.
*/ */
int move_addr_to_user(void *kaddr, int klen, void __user *uaddr, int move_addr_to_user(struct sockaddr *kaddr, int klen, void __user *uaddr,
int __user *ulen) int __user *ulen)
{ {
int err; int err;
@ -219,7 +219,7 @@ int move_addr_to_user(void *kaddr, int klen, void __user *uaddr,
return err; return err;
if (len > klen) if (len > klen)
len = klen; len = klen;
if (len < 0 || len > MAX_SOCK_ADDR) if (len < 0 || len > sizeof(struct sockaddr_storage))
return -EINVAL; return -EINVAL;
if (len) { if (len) {
if (audit_sockaddr(klen, kaddr)) if (audit_sockaddr(klen, kaddr))
@ -1342,20 +1342,20 @@ out_fd:
asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen) asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen)
{ {
struct socket *sock; struct socket *sock;
char address[MAX_SOCK_ADDR]; struct sockaddr_storage address;
int err, fput_needed; int err, fput_needed;
sock = sockfd_lookup_light(fd, &err, &fput_needed); sock = sockfd_lookup_light(fd, &err, &fput_needed);
if (sock) { if (sock) {
err = move_addr_to_kernel(umyaddr, addrlen, address); err = move_addr_to_kernel(umyaddr, addrlen, (struct sockaddr *)&address);
if (err >= 0) { if (err >= 0) {
err = security_socket_bind(sock, err = security_socket_bind(sock,
(struct sockaddr *)address, (struct sockaddr *)&address,
addrlen); addrlen);
if (!err) if (!err)
err = sock->ops->bind(sock, err = sock->ops->bind(sock,
(struct sockaddr *) (struct sockaddr *)
address, addrlen); &address, addrlen);
} }
fput_light(sock->file, fput_needed); fput_light(sock->file, fput_needed);
} }
@ -1407,7 +1407,7 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr,
struct socket *sock, *newsock; struct socket *sock, *newsock;
struct file *newfile; struct file *newfile;
int err, len, newfd, fput_needed; int err, len, newfd, fput_needed;
char address[MAX_SOCK_ADDR]; struct sockaddr_storage address;
sock = sockfd_lookup_light(fd, &err, &fput_needed); sock = sockfd_lookup_light(fd, &err, &fput_needed);
if (!sock) if (!sock)
@ -1446,13 +1446,13 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr,
goto out_fd; goto out_fd;
if (upeer_sockaddr) { if (upeer_sockaddr) {
if (newsock->ops->getname(newsock, (struct sockaddr *)address, if (newsock->ops->getname(newsock, (struct sockaddr *)&address,
&len, 2) < 0) { &len, 2) < 0) {
err = -ECONNABORTED; err = -ECONNABORTED;
goto out_fd; goto out_fd;
} }
err = move_addr_to_user(address, len, upeer_sockaddr, err = move_addr_to_user((struct sockaddr *)&address,
upeer_addrlen); len, upeer_sockaddr, upeer_addrlen);
if (err < 0) if (err < 0)
goto out_fd; goto out_fd;
} }
@ -1495,22 +1495,22 @@ asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr,
int addrlen) int addrlen)
{ {
struct socket *sock; struct socket *sock;
char address[MAX_SOCK_ADDR]; struct sockaddr_storage address;
int err, fput_needed; int err, fput_needed;
sock = sockfd_lookup_light(fd, &err, &fput_needed); sock = sockfd_lookup_light(fd, &err, &fput_needed);
if (!sock) if (!sock)
goto out; goto out;
err = move_addr_to_kernel(uservaddr, addrlen, address); err = move_addr_to_kernel(uservaddr, addrlen, (struct sockaddr *)&address);
if (err < 0) if (err < 0)
goto out_put; goto out_put;
err = err =
security_socket_connect(sock, (struct sockaddr *)address, addrlen); security_socket_connect(sock, (struct sockaddr *)&address, addrlen);
if (err) if (err)
goto out_put; goto out_put;
err = sock->ops->connect(sock, (struct sockaddr *)address, addrlen, err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen,
sock->file->f_flags); sock->file->f_flags);
out_put: out_put:
fput_light(sock->file, fput_needed); fput_light(sock->file, fput_needed);
@ -1527,7 +1527,7 @@ asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr,
int __user *usockaddr_len) int __user *usockaddr_len)
{ {
struct socket *sock; struct socket *sock;
char address[MAX_SOCK_ADDR]; struct sockaddr_storage address;
int len, err, fput_needed; int len, err, fput_needed;
sock = sockfd_lookup_light(fd, &err, &fput_needed); sock = sockfd_lookup_light(fd, &err, &fput_needed);
@ -1538,10 +1538,10 @@ asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr,
if (err) if (err)
goto out_put; goto out_put;
err = sock->ops->getname(sock, (struct sockaddr *)address, &len, 0); err = sock->ops->getname(sock, (struct sockaddr *)&address, &len, 0);
if (err) if (err)
goto out_put; goto out_put;
err = move_addr_to_user(address, len, usockaddr, usockaddr_len); err = move_addr_to_user((struct sockaddr *)&address, len, usockaddr, usockaddr_len);
out_put: out_put:
fput_light(sock->file, fput_needed); fput_light(sock->file, fput_needed);
@ -1558,7 +1558,7 @@ asmlinkage long sys_getpeername(int fd, struct sockaddr __user *usockaddr,
int __user *usockaddr_len) int __user *usockaddr_len)
{ {
struct socket *sock; struct socket *sock;
char address[MAX_SOCK_ADDR]; struct sockaddr_storage address;
int len, err, fput_needed; int len, err, fput_needed;
sock = sockfd_lookup_light(fd, &err, &fput_needed); sock = sockfd_lookup_light(fd, &err, &fput_needed);
@ -1570,10 +1570,10 @@ asmlinkage long sys_getpeername(int fd, struct sockaddr __user *usockaddr,
} }
err = err =
sock->ops->getname(sock, (struct sockaddr *)address, &len, sock->ops->getname(sock, (struct sockaddr *)&address, &len,
1); 1);
if (!err) if (!err)
err = move_addr_to_user(address, len, usockaddr, err = move_addr_to_user((struct sockaddr *)&address, len, usockaddr,
usockaddr_len); usockaddr_len);
fput_light(sock->file, fput_needed); fput_light(sock->file, fput_needed);
} }
@ -1591,7 +1591,7 @@ asmlinkage long sys_sendto(int fd, void __user *buff, size_t len,
int addr_len) int addr_len)
{ {
struct socket *sock; struct socket *sock;
char address[MAX_SOCK_ADDR]; struct sockaddr_storage address;
int err; int err;
struct msghdr msg; struct msghdr msg;
struct iovec iov; struct iovec iov;
@ -1610,10 +1610,10 @@ asmlinkage long sys_sendto(int fd, void __user *buff, size_t len,
msg.msg_controllen = 0; msg.msg_controllen = 0;
msg.msg_namelen = 0; msg.msg_namelen = 0;
if (addr) { if (addr) {
err = move_addr_to_kernel(addr, addr_len, address); err = move_addr_to_kernel(addr, addr_len, (struct sockaddr *)&address);
if (err < 0) if (err < 0)
goto out_put; goto out_put;
msg.msg_name = address; msg.msg_name = (struct sockaddr *)&address;
msg.msg_namelen = addr_len; msg.msg_namelen = addr_len;
} }
if (sock->file->f_flags & O_NONBLOCK) if (sock->file->f_flags & O_NONBLOCK)
@ -1649,7 +1649,7 @@ asmlinkage long sys_recvfrom(int fd, void __user *ubuf, size_t size,
struct socket *sock; struct socket *sock;
struct iovec iov; struct iovec iov;
struct msghdr msg; struct msghdr msg;
char address[MAX_SOCK_ADDR]; struct sockaddr_storage address;
int err, err2; int err, err2;
int fput_needed; int fput_needed;
@ -1663,14 +1663,15 @@ asmlinkage long sys_recvfrom(int fd, void __user *ubuf, size_t size,
msg.msg_iov = &iov; msg.msg_iov = &iov;
iov.iov_len = size; iov.iov_len = size;
iov.iov_base = ubuf; iov.iov_base = ubuf;
msg.msg_name = address; msg.msg_name = (struct sockaddr *)&address;
msg.msg_namelen = MAX_SOCK_ADDR; msg.msg_namelen = sizeof(address);
if (sock->file->f_flags & O_NONBLOCK) if (sock->file->f_flags & O_NONBLOCK)
flags |= MSG_DONTWAIT; flags |= MSG_DONTWAIT;
err = sock_recvmsg(sock, &msg, size, flags); err = sock_recvmsg(sock, &msg, size, flags);
if (err >= 0 && addr != NULL) { if (err >= 0 && addr != NULL) {
err2 = move_addr_to_user(address, msg.msg_namelen, addr, addr_len); err2 = move_addr_to_user((struct sockaddr *)&address,
msg.msg_namelen, addr, addr_len);
if (err2 < 0) if (err2 < 0)
err = err2; err = err2;
} }
@ -1790,7 +1791,7 @@ asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags)
struct compat_msghdr __user *msg_compat = struct compat_msghdr __user *msg_compat =
(struct compat_msghdr __user *)msg; (struct compat_msghdr __user *)msg;
struct socket *sock; struct socket *sock;
char address[MAX_SOCK_ADDR]; struct sockaddr_storage address;
struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
unsigned char ctl[sizeof(struct cmsghdr) + 20] unsigned char ctl[sizeof(struct cmsghdr) + 20]
__attribute__ ((aligned(sizeof(__kernel_size_t)))); __attribute__ ((aligned(sizeof(__kernel_size_t))));
@ -1828,9 +1829,13 @@ asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags)
/* This will also move the address data into kernel space */ /* This will also move the address data into kernel space */
if (MSG_CMSG_COMPAT & flags) { if (MSG_CMSG_COMPAT & flags) {
err = verify_compat_iovec(&msg_sys, iov, address, VERIFY_READ); err = verify_compat_iovec(&msg_sys, iov,
(struct sockaddr *)&address,
VERIFY_READ);
} else } else
err = verify_iovec(&msg_sys, iov, address, VERIFY_READ); err = verify_iovec(&msg_sys, iov,
(struct sockaddr *)&address,
VERIFY_READ);
if (err < 0) if (err < 0)
goto out_freeiov; goto out_freeiov;
total_len = err; total_len = err;
@ -1901,7 +1906,7 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg,
int fput_needed; int fput_needed;
/* kernel mode address */ /* kernel mode address */
char addr[MAX_SOCK_ADDR]; struct sockaddr_storage addr;
/* user mode address pointers */ /* user mode address pointers */
struct sockaddr __user *uaddr; struct sockaddr __user *uaddr;
@ -1939,9 +1944,13 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg,
uaddr = (__force void __user *)msg_sys.msg_name; uaddr = (__force void __user *)msg_sys.msg_name;
uaddr_len = COMPAT_NAMELEN(msg); uaddr_len = COMPAT_NAMELEN(msg);
if (MSG_CMSG_COMPAT & flags) { if (MSG_CMSG_COMPAT & flags) {
err = verify_compat_iovec(&msg_sys, iov, addr, VERIFY_WRITE); err = verify_compat_iovec(&msg_sys, iov,
(struct sockaddr *)&addr,
VERIFY_WRITE);
} else } else
err = verify_iovec(&msg_sys, iov, addr, VERIFY_WRITE); err = verify_iovec(&msg_sys, iov,
(struct sockaddr *)&addr,
VERIFY_WRITE);
if (err < 0) if (err < 0)
goto out_freeiov; goto out_freeiov;
total_len = err; total_len = err;
@ -1957,7 +1966,8 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg,
len = err; len = err;
if (uaddr != NULL) { if (uaddr != NULL) {
err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, err = move_addr_to_user((struct sockaddr *)&addr,
msg_sys.msg_namelen, uaddr,
uaddr_len); uaddr_len);
if (err < 0) if (err < 0)
goto out_freeiov; goto out_freeiov;