mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 03:27:44 -04:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (27 commits) af_unix: limit recursion level pch_gbe driver: The wrong of initializer entry pch_gbe dreiver: chang author ucc_geth: fix ucc halt problem in half duplex mode inet: Fix __inet_inherit_port() to correctly increment bsockets and num_owners ehea: Add some info messages and fix an issue hso: fix disable_net NET: wan/x25_asy, move lapb_unregister to x25_asy_close_tty cxgb4vf: fix setting unicast/multicast addresses ... net, ppp: Report correct error code if unit allocation failed DECnet: don't leak uninitialized stack byte au1000_eth: fix invalid address accessing the MAC enable register dccp: fix error in updating the GAR tcp: restrict net.ipv4.tcp_adv_win_scale (#20312) netns: Don't leak others' openreq-s in proc Net: ceph: Makefile: Remove unnessary code vhost/net: fix rcu check usage econet: fix CVE-2010-3848 econet: fix CVE-2010-3850 econet: disallow NULL remote addr for sendmsg(), fixes CVE-2010-3849 ...
This commit is contained in:
commit
a01af8e4a4
30 changed files with 280 additions and 203 deletions
|
|
@ -1,9 +1,6 @@
|
|||
#
|
||||
# Makefile for CEPH filesystem.
|
||||
#
|
||||
|
||||
ifneq ($(KERNELRELEASE),)
|
||||
|
||||
obj-$(CONFIG_CEPH_LIB) += libceph.o
|
||||
|
||||
libceph-objs := ceph_common.o messenger.o msgpool.o buffer.o pagelist.o \
|
||||
|
|
@ -16,22 +13,3 @@ libceph-objs := ceph_common.o messenger.o msgpool.o buffer.o pagelist.o \
|
|||
ceph_fs.o ceph_strings.o ceph_hash.o \
|
||||
pagevec.o
|
||||
|
||||
else
|
||||
#Otherwise we were called directly from the command
|
||||
# line; invoke the kernel build system.
|
||||
|
||||
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
|
||||
PWD := $(shell pwd)
|
||||
|
||||
default: all
|
||||
|
||||
all:
|
||||
$(MAKE) -C $(KERNELDIR) M=$(PWD) CONFIG_CEPH_LIB=m modules
|
||||
|
||||
modules_install:
|
||||
$(MAKE) -C $(KERNELDIR) M=$(PWD) CONFIG_CEPH_LIB=m modules_install
|
||||
|
||||
clean:
|
||||
$(MAKE) -C $(KERNELDIR) M=$(PWD) clean
|
||||
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -239,7 +239,8 @@ static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb)
|
|||
dccp_update_gsr(sk, seqno);
|
||||
|
||||
if (dh->dccph_type != DCCP_PKT_SYNC &&
|
||||
(ackno != DCCP_PKT_WITHOUT_ACK_SEQ))
|
||||
ackno != DCCP_PKT_WITHOUT_ACK_SEQ &&
|
||||
after48(ackno, dp->dccps_gar))
|
||||
dp->dccps_gar = ackno;
|
||||
} else {
|
||||
unsigned long now = jiffies;
|
||||
|
|
|
|||
|
|
@ -1556,6 +1556,8 @@ static int __dn_getsockopt(struct socket *sock, int level,int optname, char __us
|
|||
if (r_len > sizeof(struct linkinfo_dn))
|
||||
r_len = sizeof(struct linkinfo_dn);
|
||||
|
||||
memset(&link, 0, sizeof(link));
|
||||
|
||||
switch(sock->state) {
|
||||
case SS_CONNECTING:
|
||||
link.idn_linkstate = LL_CONNECTING;
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include <linux/skbuff.h>
|
||||
#include <linux/udp.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <net/sock.h>
|
||||
#include <net/inet_common.h>
|
||||
#include <linux/stat.h>
|
||||
|
|
@ -276,12 +277,12 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
|
|||
#endif
|
||||
#ifdef CONFIG_ECONET_AUNUDP
|
||||
struct msghdr udpmsg;
|
||||
struct iovec iov[msg->msg_iovlen+1];
|
||||
struct iovec iov[2];
|
||||
struct aunhdr ah;
|
||||
struct sockaddr_in udpdest;
|
||||
__kernel_size_t size;
|
||||
int i;
|
||||
mm_segment_t oldfs;
|
||||
char *userbuf;
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -297,23 +298,14 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
|
|||
|
||||
mutex_lock(&econet_mutex);
|
||||
|
||||
if (saddr == NULL) {
|
||||
struct econet_sock *eo = ec_sk(sk);
|
||||
|
||||
addr.station = eo->station;
|
||||
addr.net = eo->net;
|
||||
port = eo->port;
|
||||
cb = eo->cb;
|
||||
} else {
|
||||
if (msg->msg_namelen < sizeof(struct sockaddr_ec)) {
|
||||
mutex_unlock(&econet_mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
addr.station = saddr->addr.station;
|
||||
addr.net = saddr->addr.net;
|
||||
port = saddr->port;
|
||||
cb = saddr->cb;
|
||||
}
|
||||
if (saddr == NULL || msg->msg_namelen < sizeof(struct sockaddr_ec)) {
|
||||
mutex_unlock(&econet_mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
addr.station = saddr->addr.station;
|
||||
addr.net = saddr->addr.net;
|
||||
port = saddr->port;
|
||||
cb = saddr->cb;
|
||||
|
||||
/* Look for a device with the right network number. */
|
||||
dev = net2dev_map[addr.net];
|
||||
|
|
@ -328,17 +320,17 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
|
|||
}
|
||||
}
|
||||
|
||||
if (len + 15 > dev->mtu) {
|
||||
mutex_unlock(&econet_mutex);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
if (dev->type == ARPHRD_ECONET) {
|
||||
/* Real hardware Econet. We're not worthy etc. */
|
||||
#ifdef CONFIG_ECONET_NATIVE
|
||||
unsigned short proto = 0;
|
||||
int res;
|
||||
|
||||
if (len + 15 > dev->mtu) {
|
||||
mutex_unlock(&econet_mutex);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
dev_hold(dev);
|
||||
|
||||
skb = sock_alloc_send_skb(sk, len+LL_ALLOCATED_SPACE(dev),
|
||||
|
|
@ -351,7 +343,6 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
|
|||
|
||||
eb = (struct ec_cb *)&skb->cb;
|
||||
|
||||
/* BUG: saddr may be NULL */
|
||||
eb->cookie = saddr->cookie;
|
||||
eb->sec = *saddr;
|
||||
eb->sent = ec_tx_done;
|
||||
|
|
@ -415,6 +406,11 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
|
|||
return -ENETDOWN; /* No socket - can't send */
|
||||
}
|
||||
|
||||
if (len > 32768) {
|
||||
err = -E2BIG;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Make up a UDP datagram and hand it off to some higher intellect. */
|
||||
|
||||
memset(&udpdest, 0, sizeof(udpdest));
|
||||
|
|
@ -446,36 +442,26 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
|
|||
|
||||
/* tack our header on the front of the iovec */
|
||||
size = sizeof(struct aunhdr);
|
||||
/*
|
||||
* XXX: that is b0rken. We can't mix userland and kernel pointers
|
||||
* in iovec, since on a lot of platforms copy_from_user() will
|
||||
* *not* work with the kernel and userland ones at the same time,
|
||||
* regardless of what we do with set_fs(). And we are talking about
|
||||
* econet-over-ethernet here, so "it's only ARM anyway" doesn't
|
||||
* apply. Any suggestions on fixing that code? -- AV
|
||||
*/
|
||||
iov[0].iov_base = (void *)&ah;
|
||||
iov[0].iov_len = size;
|
||||
for (i = 0; i < msg->msg_iovlen; i++) {
|
||||
void __user *base = msg->msg_iov[i].iov_base;
|
||||
size_t iov_len = msg->msg_iov[i].iov_len;
|
||||
/* Check it now since we switch to KERNEL_DS later. */
|
||||
if (!access_ok(VERIFY_READ, base, iov_len)) {
|
||||
mutex_unlock(&econet_mutex);
|
||||
return -EFAULT;
|
||||
}
|
||||
iov[i+1].iov_base = base;
|
||||
iov[i+1].iov_len = iov_len;
|
||||
size += iov_len;
|
||||
|
||||
userbuf = vmalloc(len);
|
||||
if (userbuf == NULL) {
|
||||
err = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
iov[1].iov_base = userbuf;
|
||||
iov[1].iov_len = len;
|
||||
err = memcpy_fromiovec(userbuf, msg->msg_iov, len);
|
||||
if (err)
|
||||
goto error_free_buf;
|
||||
|
||||
/* Get a skbuff (no data, just holds our cb information) */
|
||||
if ((skb = sock_alloc_send_skb(sk, 0,
|
||||
msg->msg_flags & MSG_DONTWAIT,
|
||||
&err)) == NULL) {
|
||||
mutex_unlock(&econet_mutex);
|
||||
return err;
|
||||
}
|
||||
&err)) == NULL)
|
||||
goto error_free_buf;
|
||||
|
||||
eb = (struct ec_cb *)&skb->cb;
|
||||
|
||||
|
|
@ -491,7 +477,7 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
|
|||
udpmsg.msg_name = (void *)&udpdest;
|
||||
udpmsg.msg_namelen = sizeof(udpdest);
|
||||
udpmsg.msg_iov = &iov[0];
|
||||
udpmsg.msg_iovlen = msg->msg_iovlen + 1;
|
||||
udpmsg.msg_iovlen = 2;
|
||||
udpmsg.msg_control = NULL;
|
||||
udpmsg.msg_controllen = 0;
|
||||
udpmsg.msg_flags=0;
|
||||
|
|
@ -499,9 +485,13 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
|
|||
oldfs = get_fs(); set_fs(KERNEL_DS); /* More privs :-) */
|
||||
err = sock_sendmsg(udpsock, &udpmsg, size);
|
||||
set_fs(oldfs);
|
||||
|
||||
error_free_buf:
|
||||
vfree(userbuf);
|
||||
#else
|
||||
err = -EPROTOTYPE;
|
||||
#endif
|
||||
error:
|
||||
mutex_unlock(&econet_mutex);
|
||||
|
||||
return err;
|
||||
|
|
@ -671,6 +661,9 @@ static int ec_dev_ioctl(struct socket *sock, unsigned int cmd, void __user *arg)
|
|||
err = 0;
|
||||
switch (cmd) {
|
||||
case SIOCSIFADDR:
|
||||
if (!capable(CAP_NET_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
edev = dev->ec_ptr;
|
||||
if (edev == NULL) {
|
||||
/* Magic up a new one. */
|
||||
|
|
|
|||
|
|
@ -133,8 +133,7 @@ int __inet_inherit_port(struct sock *sk, struct sock *child)
|
|||
}
|
||||
}
|
||||
}
|
||||
sk_add_bind_node(child, &tb->owners);
|
||||
inet_csk(child)->icsk_bind_hash = tb;
|
||||
inet_bind_hash(child, tb, port);
|
||||
spin_unlock(&head->lock);
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ static int zero;
|
|||
static int tcp_retr1_max = 255;
|
||||
static int ip_local_port_range_min[] = { 1, 1 };
|
||||
static int ip_local_port_range_max[] = { 65535, 65535 };
|
||||
static int tcp_adv_win_scale_min = -31;
|
||||
static int tcp_adv_win_scale_max = 31;
|
||||
|
||||
/* Update system visible IP port range */
|
||||
static void set_local_port_range(int range[2])
|
||||
|
|
@ -426,7 +428,9 @@ static struct ctl_table ipv4_table[] = {
|
|||
.data = &sysctl_tcp_adv_win_scale,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec
|
||||
.proc_handler = proc_dointvec_minmax,
|
||||
.extra1 = &tcp_adv_win_scale_min,
|
||||
.extra2 = &tcp_adv_win_scale_max,
|
||||
},
|
||||
{
|
||||
.procname = "tcp_tw_reuse",
|
||||
|
|
|
|||
|
|
@ -2246,7 +2246,7 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
|
|||
/* Values greater than interface MTU won't take effect. However
|
||||
* at the point when this call is done we typically don't yet
|
||||
* know which interface is going to be used */
|
||||
if (val < 64 || val > MAX_TCP_WINDOW) {
|
||||
if (val < TCP_MIN_MSS || val > MAX_TCP_WINDOW) {
|
||||
err = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2043,7 +2043,9 @@ get_req:
|
|||
}
|
||||
get_sk:
|
||||
sk_nulls_for_each_from(sk, node) {
|
||||
if (sk->sk_family == st->family && net_eq(sock_net(sk), net)) {
|
||||
if (!net_eq(sock_net(sk), net))
|
||||
continue;
|
||||
if (sk->sk_family == st->family) {
|
||||
cur = sk;
|
||||
goto out;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1343,9 +1343,25 @@ static void unix_destruct_scm(struct sk_buff *skb)
|
|||
sock_wfree(skb);
|
||||
}
|
||||
|
||||
#define MAX_RECURSION_LEVEL 4
|
||||
|
||||
static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
|
||||
{
|
||||
int i;
|
||||
unsigned char max_level = 0;
|
||||
int unix_sock_count = 0;
|
||||
|
||||
for (i = scm->fp->count - 1; i >= 0; i--) {
|
||||
struct sock *sk = unix_get_socket(scm->fp->fp[i]);
|
||||
|
||||
if (sk) {
|
||||
unix_sock_count++;
|
||||
max_level = max(max_level,
|
||||
unix_sk(sk)->recursion_level);
|
||||
}
|
||||
}
|
||||
if (unlikely(max_level > MAX_RECURSION_LEVEL))
|
||||
return -ETOOMANYREFS;
|
||||
|
||||
/*
|
||||
* Need to duplicate file references for the sake of garbage
|
||||
|
|
@ -1356,9 +1372,11 @@ static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
|
|||
if (!UNIXCB(skb).fp)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = scm->fp->count-1; i >= 0; i--)
|
||||
unix_inflight(scm->fp->fp[i]);
|
||||
return 0;
|
||||
if (unix_sock_count) {
|
||||
for (i = scm->fp->count - 1; i >= 0; i--)
|
||||
unix_inflight(scm->fp->fp[i]);
|
||||
}
|
||||
return max_level;
|
||||
}
|
||||
|
||||
static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool send_fds)
|
||||
|
|
@ -1393,6 +1411,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
|
|||
struct sk_buff *skb;
|
||||
long timeo;
|
||||
struct scm_cookie tmp_scm;
|
||||
int max_level;
|
||||
|
||||
if (NULL == siocb->scm)
|
||||
siocb->scm = &tmp_scm;
|
||||
|
|
@ -1431,8 +1450,9 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
|
|||
goto out;
|
||||
|
||||
err = unix_scm_to_skb(siocb->scm, skb, true);
|
||||
if (err)
|
||||
if (err < 0)
|
||||
goto out_free;
|
||||
max_level = err + 1;
|
||||
unix_get_secdata(siocb->scm, skb);
|
||||
|
||||
skb_reset_transport_header(skb);
|
||||
|
|
@ -1514,6 +1534,8 @@ restart:
|
|||
if (sock_flag(other, SOCK_RCVTSTAMP))
|
||||
__net_timestamp(skb);
|
||||
skb_queue_tail(&other->sk_receive_queue, skb);
|
||||
if (max_level > unix_sk(other)->recursion_level)
|
||||
unix_sk(other)->recursion_level = max_level;
|
||||
unix_state_unlock(other);
|
||||
other->sk_data_ready(other, len);
|
||||
sock_put(other);
|
||||
|
|
@ -1544,6 +1566,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
|
|||
int sent = 0;
|
||||
struct scm_cookie tmp_scm;
|
||||
bool fds_sent = false;
|
||||
int max_level;
|
||||
|
||||
if (NULL == siocb->scm)
|
||||
siocb->scm = &tmp_scm;
|
||||
|
|
@ -1607,10 +1630,11 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
|
|||
|
||||
/* Only send the fds in the first buffer */
|
||||
err = unix_scm_to_skb(siocb->scm, skb, !fds_sent);
|
||||
if (err) {
|
||||
if (err < 0) {
|
||||
kfree_skb(skb);
|
||||
goto out_err;
|
||||
}
|
||||
max_level = err + 1;
|
||||
fds_sent = true;
|
||||
|
||||
err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
|
||||
|
|
@ -1626,6 +1650,8 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
|
|||
goto pipe_err_free;
|
||||
|
||||
skb_queue_tail(&other->sk_receive_queue, skb);
|
||||
if (max_level > unix_sk(other)->recursion_level)
|
||||
unix_sk(other)->recursion_level = max_level;
|
||||
unix_state_unlock(other);
|
||||
other->sk_data_ready(other, size);
|
||||
sent += size;
|
||||
|
|
@ -1845,6 +1871,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|||
unix_state_lock(sk);
|
||||
skb = skb_dequeue(&sk->sk_receive_queue);
|
||||
if (skb == NULL) {
|
||||
unix_sk(sk)->recursion_level = 0;
|
||||
if (copied >= target)
|
||||
goto unlock;
|
||||
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ static DECLARE_WAIT_QUEUE_HEAD(unix_gc_wait);
|
|||
unsigned int unix_tot_inflight;
|
||||
|
||||
|
||||
static struct sock *unix_get_socket(struct file *filp)
|
||||
struct sock *unix_get_socket(struct file *filp)
|
||||
{
|
||||
struct sock *u_sock = NULL;
|
||||
struct inode *inode = filp->f_path.dentry->d_inode;
|
||||
|
|
@ -259,9 +259,16 @@ static void inc_inflight_move_tail(struct unix_sock *u)
|
|||
}
|
||||
|
||||
static bool gc_in_progress = false;
|
||||
#define UNIX_INFLIGHT_TRIGGER_GC 16000
|
||||
|
||||
void wait_for_unix_gc(void)
|
||||
{
|
||||
/*
|
||||
* If number of inflight sockets is insane,
|
||||
* force a garbage collect right now.
|
||||
*/
|
||||
if (unix_tot_inflight > UNIX_INFLIGHT_TRIGGER_GC && !gc_in_progress)
|
||||
unix_gc();
|
||||
wait_event(unix_gc_wait, gc_in_progress == false);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue