mirror of
https://github.com/Fishwaldo/build.git
synced 2025-03-26 16:51:48 +00:00
1156 lines
39 KiB
Diff
1156 lines
39 KiB
Diff
diff --git a/Makefile b/Makefile
|
|
index 9f440dd8256c..656c45f09128 100644
|
|
--- a/Makefile
|
|
+++ b/Makefile
|
|
@@ -1,6 +1,6 @@
|
|
VERSION = 3
|
|
PATCHLEVEL = 4
|
|
-SUBLEVEL = 67
|
|
+SUBLEVEL = 68
|
|
EXTRAVERSION =
|
|
NAME = Saber-toothed Squirrel
|
|
|
|
diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c
|
|
index 77e1e6cd66ce..2894461e0bdb 100644
|
|
--- a/drivers/connector/cn_proc.c
|
|
+++ b/drivers/connector/cn_proc.c
|
|
@@ -64,6 +64,7 @@ void proc_fork_connector(struct task_struct *task)
|
|
|
|
msg = (struct cn_msg*)buffer;
|
|
ev = (struct proc_event*)msg->data;
|
|
+ memset(&ev->event_data, 0, sizeof(ev->event_data));
|
|
get_seq(&msg->seq, &ev->cpu);
|
|
ktime_get_ts(&ts); /* get high res monotonic timestamp */
|
|
put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
|
|
@@ -79,6 +80,7 @@ void proc_fork_connector(struct task_struct *task)
|
|
memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
|
|
msg->ack = 0; /* not used */
|
|
msg->len = sizeof(*ev);
|
|
+ msg->flags = 0; /* not used */
|
|
/* If cn_netlink_send() failed, the data is not sent */
|
|
cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
|
|
}
|
|
@@ -95,6 +97,7 @@ void proc_exec_connector(struct task_struct *task)
|
|
|
|
msg = (struct cn_msg*)buffer;
|
|
ev = (struct proc_event*)msg->data;
|
|
+ memset(&ev->event_data, 0, sizeof(ev->event_data));
|
|
get_seq(&msg->seq, &ev->cpu);
|
|
ktime_get_ts(&ts); /* get high res monotonic timestamp */
|
|
put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
|
|
@@ -105,6 +108,7 @@ void proc_exec_connector(struct task_struct *task)
|
|
memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
|
|
msg->ack = 0; /* not used */
|
|
msg->len = sizeof(*ev);
|
|
+ msg->flags = 0; /* not used */
|
|
cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
|
|
}
|
|
|
|
@@ -121,6 +125,7 @@ void proc_id_connector(struct task_struct *task, int which_id)
|
|
|
|
msg = (struct cn_msg*)buffer;
|
|
ev = (struct proc_event*)msg->data;
|
|
+ memset(&ev->event_data, 0, sizeof(ev->event_data));
|
|
ev->what = which_id;
|
|
ev->event_data.id.process_pid = task->pid;
|
|
ev->event_data.id.process_tgid = task->tgid;
|
|
@@ -144,6 +149,7 @@ void proc_id_connector(struct task_struct *task, int which_id)
|
|
memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
|
|
msg->ack = 0; /* not used */
|
|
msg->len = sizeof(*ev);
|
|
+ msg->flags = 0; /* not used */
|
|
cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
|
|
}
|
|
|
|
@@ -159,6 +165,7 @@ void proc_sid_connector(struct task_struct *task)
|
|
|
|
msg = (struct cn_msg *)buffer;
|
|
ev = (struct proc_event *)msg->data;
|
|
+ memset(&ev->event_data, 0, sizeof(ev->event_data));
|
|
get_seq(&msg->seq, &ev->cpu);
|
|
ktime_get_ts(&ts); /* get high res monotonic timestamp */
|
|
put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
|
|
@@ -169,6 +176,7 @@ void proc_sid_connector(struct task_struct *task)
|
|
memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
|
|
msg->ack = 0; /* not used */
|
|
msg->len = sizeof(*ev);
|
|
+ msg->flags = 0; /* not used */
|
|
cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
|
|
}
|
|
|
|
@@ -184,6 +192,7 @@ void proc_ptrace_connector(struct task_struct *task, int ptrace_id)
|
|
|
|
msg = (struct cn_msg *)buffer;
|
|
ev = (struct proc_event *)msg->data;
|
|
+ memset(&ev->event_data, 0, sizeof(ev->event_data));
|
|
get_seq(&msg->seq, &ev->cpu);
|
|
ktime_get_ts(&ts); /* get high res monotonic timestamp */
|
|
put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
|
|
@@ -202,6 +211,7 @@ void proc_ptrace_connector(struct task_struct *task, int ptrace_id)
|
|
memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
|
|
msg->ack = 0; /* not used */
|
|
msg->len = sizeof(*ev);
|
|
+ msg->flags = 0; /* not used */
|
|
cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
|
|
}
|
|
|
|
@@ -217,6 +227,7 @@ void proc_comm_connector(struct task_struct *task)
|
|
|
|
msg = (struct cn_msg *)buffer;
|
|
ev = (struct proc_event *)msg->data;
|
|
+ memset(&ev->event_data, 0, sizeof(ev->event_data));
|
|
get_seq(&msg->seq, &ev->cpu);
|
|
ktime_get_ts(&ts); /* get high res monotonic timestamp */
|
|
put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
|
|
@@ -228,6 +239,7 @@ void proc_comm_connector(struct task_struct *task)
|
|
memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
|
|
msg->ack = 0; /* not used */
|
|
msg->len = sizeof(*ev);
|
|
+ msg->flags = 0; /* not used */
|
|
cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
|
|
}
|
|
|
|
@@ -243,6 +255,7 @@ void proc_exit_connector(struct task_struct *task)
|
|
|
|
msg = (struct cn_msg*)buffer;
|
|
ev = (struct proc_event*)msg->data;
|
|
+ memset(&ev->event_data, 0, sizeof(ev->event_data));
|
|
get_seq(&msg->seq, &ev->cpu);
|
|
ktime_get_ts(&ts); /* get high res monotonic timestamp */
|
|
put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
|
|
@@ -255,6 +268,7 @@ void proc_exit_connector(struct task_struct *task)
|
|
memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
|
|
msg->ack = 0; /* not used */
|
|
msg->len = sizeof(*ev);
|
|
+ msg->flags = 0; /* not used */
|
|
cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
|
|
}
|
|
|
|
@@ -278,6 +292,7 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack)
|
|
|
|
msg = (struct cn_msg*)buffer;
|
|
ev = (struct proc_event*)msg->data;
|
|
+ memset(&ev->event_data, 0, sizeof(ev->event_data));
|
|
msg->seq = rcvd_seq;
|
|
ktime_get_ts(&ts); /* get high res monotonic timestamp */
|
|
put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
|
|
@@ -287,6 +302,7 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack)
|
|
memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
|
|
msg->ack = rcvd_ack + 1;
|
|
msg->len = sizeof(*ev);
|
|
+ msg->flags = 0; /* not used */
|
|
cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
|
|
}
|
|
|
|
diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c
|
|
index dde6a0fad408..ea6efe86468e 100644
|
|
--- a/drivers/connector/connector.c
|
|
+++ b/drivers/connector/connector.c
|
|
@@ -157,17 +157,18 @@ static int cn_call_callback(struct sk_buff *skb)
|
|
static void cn_rx_skb(struct sk_buff *__skb)
|
|
{
|
|
struct nlmsghdr *nlh;
|
|
- int err;
|
|
struct sk_buff *skb;
|
|
+ int len, err;
|
|
|
|
skb = skb_get(__skb);
|
|
|
|
if (skb->len >= NLMSG_SPACE(0)) {
|
|
nlh = nlmsg_hdr(skb);
|
|
+ len = nlmsg_len(nlh);
|
|
|
|
- if (nlh->nlmsg_len < sizeof(struct cn_msg) ||
|
|
+ if (len < (int)sizeof(struct cn_msg) ||
|
|
skb->len < nlh->nlmsg_len ||
|
|
- nlh->nlmsg_len > CONNECTOR_MAX_MSG_SIZE) {
|
|
+ len > CONNECTOR_MAX_MSG_SIZE) {
|
|
kfree_skb(skb);
|
|
return;
|
|
}
|
|
diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c
|
|
index 4caa8e6d59d7..2d2b1b7588d7 100644
|
|
--- a/drivers/md/dm-snap-persistent.c
|
|
+++ b/drivers/md/dm-snap-persistent.c
|
|
@@ -269,6 +269,14 @@ static chunk_t area_location(struct pstore *ps, chunk_t area)
|
|
return NUM_SNAPSHOT_HDR_CHUNKS + ((ps->exceptions_per_area + 1) * area);
|
|
}
|
|
|
|
+static void skip_metadata(struct pstore *ps)
|
|
+{
|
|
+ uint32_t stride = ps->exceptions_per_area + 1;
|
|
+ chunk_t next_free = ps->next_free;
|
|
+ if (sector_div(next_free, stride) == NUM_SNAPSHOT_HDR_CHUNKS)
|
|
+ ps->next_free++;
|
|
+}
|
|
+
|
|
/*
|
|
* Read or write a metadata area. Remembering to skip the first
|
|
* chunk which holds the header.
|
|
@@ -502,6 +510,8 @@ static int read_exceptions(struct pstore *ps,
|
|
|
|
ps->current_area--;
|
|
|
|
+ skip_metadata(ps);
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
@@ -616,8 +626,6 @@ static int persistent_prepare_exception(struct dm_exception_store *store,
|
|
struct dm_exception *e)
|
|
{
|
|
struct pstore *ps = get_info(store);
|
|
- uint32_t stride;
|
|
- chunk_t next_free;
|
|
sector_t size = get_dev_size(dm_snap_cow(store->snap)->bdev);
|
|
|
|
/* Is there enough room ? */
|
|
@@ -630,10 +638,8 @@ static int persistent_prepare_exception(struct dm_exception_store *store,
|
|
* Move onto the next free pending, making sure to take
|
|
* into account the location of the metadata chunks.
|
|
*/
|
|
- stride = (ps->exceptions_per_area + 1);
|
|
- next_free = ++ps->next_free;
|
|
- if (sector_div(next_free, stride) == 1)
|
|
- ps->next_free++;
|
|
+ ps->next_free++;
|
|
+ skip_metadata(ps);
|
|
|
|
atomic_inc(&ps->pending_count);
|
|
return 0;
|
|
diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c
|
|
index e86f4c37f981..c2cdefa1651e 100644
|
|
--- a/drivers/net/can/dev.c
|
|
+++ b/drivers/net/can/dev.c
|
|
@@ -665,14 +665,14 @@ static size_t can_get_size(const struct net_device *dev)
|
|
size_t size;
|
|
|
|
size = nla_total_size(sizeof(u32)); /* IFLA_CAN_STATE */
|
|
- size += sizeof(struct can_ctrlmode); /* IFLA_CAN_CTRLMODE */
|
|
+ size += nla_total_size(sizeof(struct can_ctrlmode)); /* IFLA_CAN_CTRLMODE */
|
|
size += nla_total_size(sizeof(u32)); /* IFLA_CAN_RESTART_MS */
|
|
- size += sizeof(struct can_bittiming); /* IFLA_CAN_BITTIMING */
|
|
- size += sizeof(struct can_clock); /* IFLA_CAN_CLOCK */
|
|
+ size += nla_total_size(sizeof(struct can_bittiming)); /* IFLA_CAN_BITTIMING */
|
|
+ size += nla_total_size(sizeof(struct can_clock)); /* IFLA_CAN_CLOCK */
|
|
if (priv->do_get_berr_counter) /* IFLA_CAN_BERR_COUNTER */
|
|
- size += sizeof(struct can_berr_counter);
|
|
+ size += nla_total_size(sizeof(struct can_berr_counter));
|
|
if (priv->bittiming_const) /* IFLA_CAN_BITTIMING_CONST */
|
|
- size += sizeof(struct can_bittiming_const);
|
|
+ size += nla_total_size(sizeof(struct can_bittiming_const));
|
|
|
|
return size;
|
|
}
|
|
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
|
|
index acd824660367..e45b8b6d6848 100644
|
|
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
|
|
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
|
|
@@ -547,6 +547,7 @@ static inline void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
|
|
skb, cqe, cqe_idx)) {
|
|
if (tpa_info->parsing_flags & PARSING_FLAGS_VLAN)
|
|
__vlan_hwaccel_put_tag(skb, tpa_info->vlan_tag);
|
|
+ skb_record_rx_queue(skb, fp->rx_queue);
|
|
napi_gro_receive(&fp->napi, skb);
|
|
} else {
|
|
DP(NETIF_MSG_RX_STATUS,
|
|
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
|
|
index 5e1ca0f05090..ffa6a72dcc60 100644
|
|
--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
|
|
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
|
|
@@ -1274,15 +1274,13 @@ static void mib_counters_update(struct mv643xx_eth_private *mp)
|
|
p->rx_discard += rdlp(mp, RX_DISCARD_FRAME_CNT);
|
|
p->rx_overrun += rdlp(mp, RX_OVERRUN_FRAME_CNT);
|
|
spin_unlock_bh(&mp->mib_counters_lock);
|
|
-
|
|
- mod_timer(&mp->mib_counters_timer, jiffies + 30 * HZ);
|
|
}
|
|
|
|
static void mib_counters_timer_wrapper(unsigned long _mp)
|
|
{
|
|
struct mv643xx_eth_private *mp = (void *)_mp;
|
|
-
|
|
mib_counters_update(mp);
|
|
+ mod_timer(&mp->mib_counters_timer, jiffies + 30 * HZ);
|
|
}
|
|
|
|
|
|
@@ -2370,6 +2368,7 @@ static int mv643xx_eth_open(struct net_device *dev)
|
|
mp->int_mask |= INT_TX_END_0 << i;
|
|
}
|
|
|
|
+ add_timer(&mp->mib_counters_timer);
|
|
port_start(mp);
|
|
|
|
wrlp(mp, INT_MASK_EXT, INT_EXT_LINK_PHY | INT_EXT_TX);
|
|
@@ -2911,7 +2910,6 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
|
|
mp->mib_counters_timer.data = (unsigned long)mp;
|
|
mp->mib_counters_timer.function = mib_counters_timer_wrapper;
|
|
mp->mib_counters_timer.expires = jiffies + 30 * HZ;
|
|
- add_timer(&mp->mib_counters_timer);
|
|
|
|
spin_lock_init(&mp->mib_counters_lock);
|
|
|
|
diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c
|
|
index 43fada572596..c336d36cf5ca 100644
|
|
--- a/drivers/net/ethernet/ti/davinci_emac.c
|
|
+++ b/drivers/net/ethernet/ti/davinci_emac.c
|
|
@@ -875,8 +875,7 @@ static void emac_dev_mcast_set(struct net_device *ndev)
|
|
netdev_mc_count(ndev) > EMAC_DEF_MAX_MULTICAST_ADDRESSES) {
|
|
mbp_enable = (mbp_enable | EMAC_MBP_RXMCAST);
|
|
emac_add_mcast(priv, EMAC_ALL_MULTI_SET, NULL);
|
|
- }
|
|
- if (!netdev_mc_empty(ndev)) {
|
|
+ } else if (!netdev_mc_empty(ndev)) {
|
|
struct netdev_hw_addr *ha;
|
|
|
|
mbp_enable = (mbp_enable | EMAC_MBP_RXMCAST);
|
|
diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c
|
|
index 1a623183cbe5..3710427c3fe1 100644
|
|
--- a/drivers/net/wan/farsync.c
|
|
+++ b/drivers/net/wan/farsync.c
|
|
@@ -1972,6 +1972,7 @@ fst_get_iface(struct fst_card_info *card, struct fst_port_info *port,
|
|
}
|
|
|
|
i = port->index;
|
|
+ memset(&sync, 0, sizeof(sync));
|
|
sync.clock_rate = FST_RDL(card, portConfig[i].lineSpeed);
|
|
/* Lucky card and linux use same encoding here */
|
|
sync.clock_type = FST_RDB(card, portConfig[i].internalClock) ==
|
|
diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c
|
|
index feb7541b33fb..ccd496bf32d9 100644
|
|
--- a/drivers/net/wan/wanxl.c
|
|
+++ b/drivers/net/wan/wanxl.c
|
|
@@ -355,6 +355,7 @@ static int wanxl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
|
ifr->ifr_settings.size = size; /* data size wanted */
|
|
return -ENOBUFS;
|
|
}
|
|
+ memset(&line, 0, sizeof(line));
|
|
line.clock_type = get_status(port)->clocking;
|
|
line.clock_rate = 0;
|
|
line.loopback = 0;
|
|
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
|
|
index 9def72f018e0..b3440c66a995 100644
|
|
--- a/drivers/usb/serial/option.c
|
|
+++ b/drivers/usb/serial/option.c
|
|
@@ -457,6 +457,10 @@ static void option_instat_callback(struct urb *urb);
|
|
#define CHANGHONG_VENDOR_ID 0x2077
|
|
#define CHANGHONG_PRODUCT_CH690 0x7001
|
|
|
|
+/* Inovia */
|
|
+#define INOVIA_VENDOR_ID 0x20a6
|
|
+#define INOVIA_SEW858 0x1105
|
|
+
|
|
/* some devices interfaces need special handling due to a number of reasons */
|
|
enum option_blacklist_reason {
|
|
OPTION_BLACKLIST_NONE = 0,
|
|
@@ -1279,7 +1283,9 @@ static const struct usb_device_id option_ids[] = {
|
|
|
|
{ USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) },
|
|
{ USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD145) },
|
|
- { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD200) },
|
|
+ { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD200),
|
|
+ .driver_info = (kernel_ulong_t)&net_intf6_blacklist
|
|
+ },
|
|
{ USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */
|
|
{ USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_GT_B3730, USB_CLASS_CDC_DATA, 0x00, 0x00) }, /* Samsung GT-B3730 LTE USB modem.*/
|
|
{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM600) },
|
|
@@ -1367,6 +1373,7 @@ static const struct usb_device_id option_ids[] = {
|
|
{ USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x00, 0x00) },
|
|
{ USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e01, 0xff, 0xff, 0xff) }, /* D-Link DWM-152/C1 */
|
|
{ USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e02, 0xff, 0xff, 0xff) }, /* D-Link DWM-156/C1 */
|
|
+ { USB_DEVICE(INOVIA_VENDOR_ID, INOVIA_SEW858) },
|
|
{ } /* Terminating entry */
|
|
};
|
|
MODULE_DEVICE_TABLE(usb, option_ids);
|
|
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
|
|
index a7492ba5371a..1b0430e00b75 100644
|
|
--- a/drivers/usb/serial/ti_usb_3410_5052.c
|
|
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
|
|
@@ -210,6 +210,7 @@ static struct usb_device_id ti_id_table_combined[19+2*TI_EXTRA_VID_PID_COUNT+1]
|
|
{ USB_DEVICE(IBM_VENDOR_ID, IBM_454B_PRODUCT_ID) },
|
|
{ USB_DEVICE(IBM_VENDOR_ID, IBM_454C_PRODUCT_ID) },
|
|
{ USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_PRODUCT_ID) },
|
|
+ { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_STRIP_PORT_ID) },
|
|
{ USB_DEVICE(TI_VENDOR_ID, FRI2_PRODUCT_ID) },
|
|
{ }
|
|
};
|
|
diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c
|
|
index cc761ad8fa57..92490e9f85ca 100644
|
|
--- a/fs/ext3/dir.c
|
|
+++ b/fs/ext3/dir.c
|
|
@@ -21,30 +21,15 @@
|
|
*
|
|
*/
|
|
|
|
+#include <linux/compat.h>
|
|
#include "ext3.h"
|
|
|
|
static unsigned char ext3_filetype_table[] = {
|
|
DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK
|
|
};
|
|
|
|
-static int ext3_readdir(struct file *, void *, filldir_t);
|
|
static int ext3_dx_readdir(struct file * filp,
|
|
void * dirent, filldir_t filldir);
|
|
-static int ext3_release_dir (struct inode * inode,
|
|
- struct file * filp);
|
|
-
|
|
-const struct file_operations ext3_dir_operations = {
|
|
- .llseek = generic_file_llseek,
|
|
- .read = generic_read_dir,
|
|
- .readdir = ext3_readdir, /* we take BKL. needed?*/
|
|
- .unlocked_ioctl = ext3_ioctl,
|
|
-#ifdef CONFIG_COMPAT
|
|
- .compat_ioctl = ext3_compat_ioctl,
|
|
-#endif
|
|
- .fsync = ext3_sync_file, /* BKL held */
|
|
- .release = ext3_release_dir,
|
|
-};
|
|
-
|
|
|
|
static unsigned char get_dtype(struct super_block *sb, int filetype)
|
|
{
|
|
@@ -55,6 +40,25 @@ static unsigned char get_dtype(struct super_block *sb, int filetype)
|
|
return (ext3_filetype_table[filetype]);
|
|
}
|
|
|
|
+/**
|
|
+ * Check if the given dir-inode refers to an htree-indexed directory
|
|
+ * (or a directory which chould potentially get coverted to use htree
|
|
+ * indexing).
|
|
+ *
|
|
+ * Return 1 if it is a dx dir, 0 if not
|
|
+ */
|
|
+static int is_dx_dir(struct inode *inode)
|
|
+{
|
|
+ struct super_block *sb = inode->i_sb;
|
|
+
|
|
+ if (EXT3_HAS_COMPAT_FEATURE(inode->i_sb,
|
|
+ EXT3_FEATURE_COMPAT_DIR_INDEX) &&
|
|
+ ((EXT3_I(inode)->i_flags & EXT3_INDEX_FL) ||
|
|
+ ((inode->i_size >> sb->s_blocksize_bits) == 1)))
|
|
+ return 1;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
|
|
int ext3_check_dir_entry (const char * function, struct inode * dir,
|
|
struct ext3_dir_entry_2 * de,
|
|
@@ -94,18 +98,13 @@ static int ext3_readdir(struct file * filp,
|
|
unsigned long offset;
|
|
int i, stored;
|
|
struct ext3_dir_entry_2 *de;
|
|
- struct super_block *sb;
|
|
int err;
|
|
struct inode *inode = filp->f_path.dentry->d_inode;
|
|
+ struct super_block *sb = inode->i_sb;
|
|
int ret = 0;
|
|
int dir_has_error = 0;
|
|
|
|
- sb = inode->i_sb;
|
|
-
|
|
- if (EXT3_HAS_COMPAT_FEATURE(inode->i_sb,
|
|
- EXT3_FEATURE_COMPAT_DIR_INDEX) &&
|
|
- ((EXT3_I(inode)->i_flags & EXT3_INDEX_FL) ||
|
|
- ((inode->i_size >> sb->s_blocksize_bits) == 1))) {
|
|
+ if (is_dx_dir(inode)) {
|
|
err = ext3_dx_readdir(filp, dirent, filldir);
|
|
if (err != ERR_BAD_DX_DIR) {
|
|
ret = err;
|
|
@@ -227,22 +226,87 @@ out:
|
|
return ret;
|
|
}
|
|
|
|
+static inline int is_32bit_api(void)
|
|
+{
|
|
+#ifdef CONFIG_COMPAT
|
|
+ return is_compat_task();
|
|
+#else
|
|
+ return (BITS_PER_LONG == 32);
|
|
+#endif
|
|
+}
|
|
+
|
|
/*
|
|
* These functions convert from the major/minor hash to an f_pos
|
|
- * value.
|
|
+ * value for dx directories
|
|
*
|
|
- * Currently we only use major hash numer. This is unfortunate, but
|
|
- * on 32-bit machines, the same VFS interface is used for lseek and
|
|
- * llseek, so if we use the 64 bit offset, then the 32-bit versions of
|
|
- * lseek/telldir/seekdir will blow out spectacularly, and from within
|
|
- * the ext2 low-level routine, we don't know if we're being called by
|
|
- * a 64-bit version of the system call or the 32-bit version of the
|
|
- * system call. Worse yet, NFSv2 only allows for a 32-bit readdir
|
|
- * cookie. Sigh.
|
|
+ * Upper layer (for example NFS) should specify FMODE_32BITHASH or
|
|
+ * FMODE_64BITHASH explicitly. On the other hand, we allow ext3 to be mounted
|
|
+ * directly on both 32-bit and 64-bit nodes, under such case, neither
|
|
+ * FMODE_32BITHASH nor FMODE_64BITHASH is specified.
|
|
*/
|
|
-#define hash2pos(major, minor) (major >> 1)
|
|
-#define pos2maj_hash(pos) ((pos << 1) & 0xffffffff)
|
|
-#define pos2min_hash(pos) (0)
|
|
+static inline loff_t hash2pos(struct file *filp, __u32 major, __u32 minor)
|
|
+{
|
|
+ if ((filp->f_mode & FMODE_32BITHASH) ||
|
|
+ (!(filp->f_mode & FMODE_64BITHASH) && is_32bit_api()))
|
|
+ return major >> 1;
|
|
+ else
|
|
+ return ((__u64)(major >> 1) << 32) | (__u64)minor;
|
|
+}
|
|
+
|
|
+static inline __u32 pos2maj_hash(struct file *filp, loff_t pos)
|
|
+{
|
|
+ if ((filp->f_mode & FMODE_32BITHASH) ||
|
|
+ (!(filp->f_mode & FMODE_64BITHASH) && is_32bit_api()))
|
|
+ return (pos << 1) & 0xffffffff;
|
|
+ else
|
|
+ return ((pos >> 32) << 1) & 0xffffffff;
|
|
+}
|
|
+
|
|
+static inline __u32 pos2min_hash(struct file *filp, loff_t pos)
|
|
+{
|
|
+ if ((filp->f_mode & FMODE_32BITHASH) ||
|
|
+ (!(filp->f_mode & FMODE_64BITHASH) && is_32bit_api()))
|
|
+ return 0;
|
|
+ else
|
|
+ return pos & 0xffffffff;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Return 32- or 64-bit end-of-file for dx directories
|
|
+ */
|
|
+static inline loff_t ext3_get_htree_eof(struct file *filp)
|
|
+{
|
|
+ if ((filp->f_mode & FMODE_32BITHASH) ||
|
|
+ (!(filp->f_mode & FMODE_64BITHASH) && is_32bit_api()))
|
|
+ return EXT3_HTREE_EOF_32BIT;
|
|
+ else
|
|
+ return EXT3_HTREE_EOF_64BIT;
|
|
+}
|
|
+
|
|
+
|
|
+/*
|
|
+ * ext3_dir_llseek() calls generic_file_llseek[_size]() to handle both
|
|
+ * non-htree and htree directories, where the "offset" is in terms
|
|
+ * of the filename hash value instead of the byte offset.
|
|
+ *
|
|
+ * Because we may return a 64-bit hash that is well beyond s_maxbytes,
|
|
+ * we need to pass the max hash as the maximum allowable offset in
|
|
+ * the htree directory case.
|
|
+ *
|
|
+ * NOTE: offsets obtained *before* ext3_set_inode_flag(dir, EXT3_INODE_INDEX)
|
|
+ * will be invalid once the directory was converted into a dx directory
|
|
+ */
|
|
+loff_t ext3_dir_llseek(struct file *file, loff_t offset, int origin)
|
|
+{
|
|
+ struct inode *inode = file->f_mapping->host;
|
|
+ int dx_dir = is_dx_dir(inode);
|
|
+
|
|
+ if (likely(dx_dir))
|
|
+ return generic_file_llseek_size(file, offset, origin,
|
|
+ ext3_get_htree_eof(file));
|
|
+ else
|
|
+ return generic_file_llseek(file, offset, origin);
|
|
+}
|
|
|
|
/*
|
|
* This structure holds the nodes of the red-black tree used to store
|
|
@@ -303,15 +367,16 @@ static void free_rb_tree_fname(struct rb_root *root)
|
|
}
|
|
|
|
|
|
-static struct dir_private_info *ext3_htree_create_dir_info(loff_t pos)
|
|
+static struct dir_private_info *ext3_htree_create_dir_info(struct file *filp,
|
|
+ loff_t pos)
|
|
{
|
|
struct dir_private_info *p;
|
|
|
|
p = kzalloc(sizeof(struct dir_private_info), GFP_KERNEL);
|
|
if (!p)
|
|
return NULL;
|
|
- p->curr_hash = pos2maj_hash(pos);
|
|
- p->curr_minor_hash = pos2min_hash(pos);
|
|
+ p->curr_hash = pos2maj_hash(filp, pos);
|
|
+ p->curr_minor_hash = pos2min_hash(filp, pos);
|
|
return p;
|
|
}
|
|
|
|
@@ -401,7 +466,7 @@ static int call_filldir(struct file * filp, void * dirent,
|
|
printk("call_filldir: called with null fname?!?\n");
|
|
return 0;
|
|
}
|
|
- curr_pos = hash2pos(fname->hash, fname->minor_hash);
|
|
+ curr_pos = hash2pos(filp, fname->hash, fname->minor_hash);
|
|
while (fname) {
|
|
error = filldir(dirent, fname->name,
|
|
fname->name_len, curr_pos,
|
|
@@ -426,13 +491,13 @@ static int ext3_dx_readdir(struct file * filp,
|
|
int ret;
|
|
|
|
if (!info) {
|
|
- info = ext3_htree_create_dir_info(filp->f_pos);
|
|
+ info = ext3_htree_create_dir_info(filp, filp->f_pos);
|
|
if (!info)
|
|
return -ENOMEM;
|
|
filp->private_data = info;
|
|
}
|
|
|
|
- if (filp->f_pos == EXT3_HTREE_EOF)
|
|
+ if (filp->f_pos == ext3_get_htree_eof(filp))
|
|
return 0; /* EOF */
|
|
|
|
/* Some one has messed with f_pos; reset the world */
|
|
@@ -440,8 +505,8 @@ static int ext3_dx_readdir(struct file * filp,
|
|
free_rb_tree_fname(&info->root);
|
|
info->curr_node = NULL;
|
|
info->extra_fname = NULL;
|
|
- info->curr_hash = pos2maj_hash(filp->f_pos);
|
|
- info->curr_minor_hash = pos2min_hash(filp->f_pos);
|
|
+ info->curr_hash = pos2maj_hash(filp, filp->f_pos);
|
|
+ info->curr_minor_hash = pos2min_hash(filp, filp->f_pos);
|
|
}
|
|
|
|
/*
|
|
@@ -473,7 +538,7 @@ static int ext3_dx_readdir(struct file * filp,
|
|
if (ret < 0)
|
|
return ret;
|
|
if (ret == 0) {
|
|
- filp->f_pos = EXT3_HTREE_EOF;
|
|
+ filp->f_pos = ext3_get_htree_eof(filp);
|
|
break;
|
|
}
|
|
info->curr_node = rb_first(&info->root);
|
|
@@ -493,7 +558,7 @@ static int ext3_dx_readdir(struct file * filp,
|
|
info->curr_minor_hash = fname->minor_hash;
|
|
} else {
|
|
if (info->next_hash == ~0) {
|
|
- filp->f_pos = EXT3_HTREE_EOF;
|
|
+ filp->f_pos = ext3_get_htree_eof(filp);
|
|
break;
|
|
}
|
|
info->curr_hash = info->next_hash;
|
|
@@ -512,3 +577,15 @@ static int ext3_release_dir (struct inode * inode, struct file * filp)
|
|
|
|
return 0;
|
|
}
|
|
+
|
|
+const struct file_operations ext3_dir_operations = {
|
|
+ .llseek = ext3_dir_llseek,
|
|
+ .read = generic_read_dir,
|
|
+ .readdir = ext3_readdir,
|
|
+ .unlocked_ioctl = ext3_ioctl,
|
|
+#ifdef CONFIG_COMPAT
|
|
+ .compat_ioctl = ext3_compat_ioctl,
|
|
+#endif
|
|
+ .fsync = ext3_sync_file,
|
|
+ .release = ext3_release_dir,
|
|
+};
|
|
diff --git a/fs/ext3/ext3.h b/fs/ext3/ext3.h
|
|
index b6515fd7e56c..fe5bef7914ea 100644
|
|
--- a/fs/ext3/ext3.h
|
|
+++ b/fs/ext3/ext3.h
|
|
@@ -920,7 +920,11 @@ struct dx_hash_info
|
|
u32 *seed;
|
|
};
|
|
|
|
-#define EXT3_HTREE_EOF 0x7fffffff
|
|
+
|
|
+/* 32 and 64 bit signed EOF for dx directories */
|
|
+#define EXT3_HTREE_EOF_32BIT ((1UL << (32 - 1)) - 1)
|
|
+#define EXT3_HTREE_EOF_64BIT ((1ULL << (64 - 1)) - 1)
|
|
+
|
|
|
|
/*
|
|
* Control parameters used by ext3_htree_next_block
|
|
diff --git a/fs/ext3/hash.c b/fs/ext3/hash.c
|
|
index d10231ddcf8a..ede315cdf126 100644
|
|
--- a/fs/ext3/hash.c
|
|
+++ b/fs/ext3/hash.c
|
|
@@ -198,8 +198,8 @@ int ext3fs_dirhash(const char *name, int len, struct dx_hash_info *hinfo)
|
|
return -1;
|
|
}
|
|
hash = hash & ~1;
|
|
- if (hash == (EXT3_HTREE_EOF << 1))
|
|
- hash = (EXT3_HTREE_EOF-1) << 1;
|
|
+ if (hash == (EXT3_HTREE_EOF_32BIT << 1))
|
|
+ hash = (EXT3_HTREE_EOF_32BIT - 1) << 1;
|
|
hinfo->hash = hash;
|
|
hinfo->minor_hash = minor_hash;
|
|
return 0;
|
|
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
|
|
index dc4d49a0c07d..42b919c36da1 100644
|
|
--- a/include/linux/skbuff.h
|
|
+++ b/include/linux/skbuff.h
|
|
@@ -760,6 +760,16 @@ static inline int skb_cloned(const struct sk_buff *skb)
|
|
(atomic_read(&skb_shinfo(skb)->dataref) & SKB_DATAREF_MASK) != 1;
|
|
}
|
|
|
|
+static inline int skb_unclone(struct sk_buff *skb, gfp_t pri)
|
|
+{
|
|
+ might_sleep_if(pri & __GFP_WAIT);
|
|
+
|
|
+ if (skb_cloned(skb))
|
|
+ return pskb_expand_head(skb, 0, 0, pri);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
/**
|
|
* skb_header_cloned - is the header a clone
|
|
* @skb: buffer to check
|
|
@@ -1198,6 +1208,11 @@ static inline int skb_pagelen(const struct sk_buff *skb)
|
|
return len + skb_headlen(skb);
|
|
}
|
|
|
|
+static inline bool skb_has_frags(const struct sk_buff *skb)
|
|
+{
|
|
+ return skb_shinfo(skb)->nr_frags;
|
|
+}
|
|
+
|
|
/**
|
|
* __skb_fill_page_desc - initialise a paged fragment in an skb
|
|
* @skb: buffer containing fragment to be initialised
|
|
diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h
|
|
index a7a683e30b64..a8c2ef6d3b93 100644
|
|
--- a/include/net/cipso_ipv4.h
|
|
+++ b/include/net/cipso_ipv4.h
|
|
@@ -290,6 +290,7 @@ static inline int cipso_v4_validate(const struct sk_buff *skb,
|
|
unsigned char err_offset = 0;
|
|
u8 opt_len = opt[1];
|
|
u8 opt_iter;
|
|
+ u8 tag_len;
|
|
|
|
if (opt_len < 8) {
|
|
err_offset = 1;
|
|
@@ -302,11 +303,12 @@ static inline int cipso_v4_validate(const struct sk_buff *skb,
|
|
}
|
|
|
|
for (opt_iter = 6; opt_iter < opt_len;) {
|
|
- if (opt[opt_iter + 1] > (opt_len - opt_iter)) {
|
|
+ tag_len = opt[opt_iter + 1];
|
|
+ if ((tag_len == 0) || (opt[opt_iter + 1] > (opt_len - opt_iter))) {
|
|
err_offset = opt_iter + 1;
|
|
goto out;
|
|
}
|
|
- opt_iter += opt[opt_iter + 1];
|
|
+ opt_iter += tag_len;
|
|
}
|
|
|
|
out:
|
|
diff --git a/include/net/dst.h b/include/net/dst.h
|
|
index 8197eadca819..1efe71aad089 100644
|
|
--- a/include/net/dst.h
|
|
+++ b/include/net/dst.h
|
|
@@ -464,10 +464,22 @@ static inline struct dst_entry *xfrm_lookup(struct net *net,
|
|
{
|
|
return dst_orig;
|
|
}
|
|
+
|
|
+static inline struct xfrm_state *dst_xfrm(const struct dst_entry *dst)
|
|
+{
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
#else
|
|
extern struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig,
|
|
const struct flowi *fl, struct sock *sk,
|
|
int flags);
|
|
+
|
|
+/* skb attached with this dst needs transformation if dst->xfrm is valid */
|
|
+static inline struct xfrm_state *dst_xfrm(const struct dst_entry *dst)
|
|
+{
|
|
+ return dst->xfrm;
|
|
+}
|
|
#endif
|
|
|
|
#endif /* _NET_DST_H */
|
|
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
|
|
index bc8465f579a8..3b15e2a147a2 100644
|
|
--- a/mm/page-writeback.c
|
|
+++ b/mm/page-writeback.c
|
|
@@ -1072,11 +1072,11 @@ static unsigned long dirty_poll_interval(unsigned long dirty,
|
|
return 1;
|
|
}
|
|
|
|
-static long bdi_max_pause(struct backing_dev_info *bdi,
|
|
- unsigned long bdi_dirty)
|
|
+static unsigned long bdi_max_pause(struct backing_dev_info *bdi,
|
|
+ unsigned long bdi_dirty)
|
|
{
|
|
- long bw = bdi->avg_write_bandwidth;
|
|
- long t;
|
|
+ unsigned long bw = bdi->avg_write_bandwidth;
|
|
+ unsigned long t;
|
|
|
|
/*
|
|
* Limit pause time for small memory systems. If sleeping for too long
|
|
@@ -1088,7 +1088,7 @@ static long bdi_max_pause(struct backing_dev_info *bdi,
|
|
t = bdi_dirty / (1 + bw / roundup_pow_of_two(1 + HZ / 8));
|
|
t++;
|
|
|
|
- return min_t(long, t, MAX_PAUSE);
|
|
+ return min_t(unsigned long, t, MAX_PAUSE);
|
|
}
|
|
|
|
static long bdi_min_pause(struct backing_dev_info *bdi,
|
|
diff --git a/net/8021q/vlan_netlink.c b/net/8021q/vlan_netlink.c
|
|
index 50711368ad6a..7f046b4c06bc 100644
|
|
--- a/net/8021q/vlan_netlink.c
|
|
+++ b/net/8021q/vlan_netlink.c
|
|
@@ -152,7 +152,7 @@ static size_t vlan_get_size(const struct net_device *dev)
|
|
struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
|
|
|
|
return nla_total_size(2) + /* IFLA_VLAN_ID */
|
|
- sizeof(struct ifla_vlan_flags) + /* IFLA_VLAN_FLAGS */
|
|
+ nla_total_size(sizeof(struct ifla_vlan_flags)) + /* IFLA_VLAN_FLAGS */
|
|
vlan_qos_map_size(vlan->nr_ingress_mappings) +
|
|
vlan_qos_map_size(vlan->nr_egress_mappings);
|
|
}
|
|
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
|
|
index f774796f7e57..2f100ccef86f 100644
|
|
--- a/net/bridge/br_stp_if.c
|
|
+++ b/net/bridge/br_stp_if.c
|
|
@@ -134,7 +134,7 @@ static void br_stp_start(struct net_bridge *br)
|
|
|
|
if (br->bridge_forward_delay < BR_MIN_FORWARD_DELAY)
|
|
__br_set_forward_delay(br, BR_MIN_FORWARD_DELAY);
|
|
- else if (br->bridge_forward_delay < BR_MAX_FORWARD_DELAY)
|
|
+ else if (br->bridge_forward_delay > BR_MAX_FORWARD_DELAY)
|
|
__br_set_forward_delay(br, BR_MAX_FORWARD_DELAY);
|
|
|
|
if (r == 0) {
|
|
diff --git a/net/compat.c b/net/compat.c
|
|
index 014e1c78ecc5..ee84d82d7287 100644
|
|
--- a/net/compat.c
|
|
+++ b/net/compat.c
|
|
@@ -71,6 +71,8 @@ int get_compat_msghdr(struct msghdr *kmsg, struct compat_msghdr __user *umsg)
|
|
__get_user(kmsg->msg_controllen, &umsg->msg_controllen) ||
|
|
__get_user(kmsg->msg_flags, &umsg->msg_flags))
|
|
return -EFAULT;
|
|
+ if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
|
|
+ return -EINVAL;
|
|
kmsg->msg_name = compat_ptr(tmp1);
|
|
kmsg->msg_iov = compat_ptr(tmp2);
|
|
kmsg->msg_control = compat_ptr(tmp3);
|
|
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
|
|
index 984ec656b03b..4afcf31bdfeb 100644
|
|
--- a/net/ipv4/inet_hashtables.c
|
|
+++ b/net/ipv4/inet_hashtables.c
|
|
@@ -268,7 +268,7 @@ begintw:
|
|
}
|
|
if (unlikely(!INET_TW_MATCH(sk, net, hash, acookie,
|
|
saddr, daddr, ports, dif))) {
|
|
- sock_put(sk);
|
|
+ inet_twsk_put(inet_twsk(sk));
|
|
goto begintw;
|
|
}
|
|
goto out;
|
|
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
|
|
index 3bc4c978d7ad..d6407b563fd8 100644
|
|
--- a/net/ipv4/ip_output.c
|
|
+++ b/net/ipv4/ip_output.c
|
|
@@ -846,7 +846,7 @@ static int __ip_append_data(struct sock *sk,
|
|
csummode = CHECKSUM_PARTIAL;
|
|
|
|
cork->length += length;
|
|
- if (((length > mtu) || (skb && skb_is_gso(skb))) &&
|
|
+ if (((length > mtu) || (skb && skb_has_frags(skb))) &&
|
|
(sk->sk_protocol == IPPROTO_UDP) &&
|
|
(rt->dst.dev->features & NETIF_F_UFO) && !rt->dst.header_len) {
|
|
err = ip_ufo_append_data(sk, queue, getfrag, from, length,
|
|
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
|
|
index 167ea10b521a..108c73d760df 100644
|
|
--- a/net/ipv4/route.c
|
|
+++ b/net/ipv4/route.c
|
|
@@ -2713,7 +2713,7 @@ static struct rtable *ip_route_output_slow(struct net *net, struct flowi4 *fl4)
|
|
RT_SCOPE_LINK);
|
|
goto make_route;
|
|
}
|
|
- if (fl4->saddr) {
|
|
+ if (!fl4->saddr) {
|
|
if (ipv4_is_multicast(fl4->daddr))
|
|
fl4->saddr = inet_select_addr(dev_out, 0,
|
|
fl4->flowi4_scope);
|
|
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
|
|
index 55d96c392e7f..99eb909c9d5f 100644
|
|
--- a/net/ipv4/tcp_input.c
|
|
+++ b/net/ipv4/tcp_input.c
|
|
@@ -1468,7 +1468,10 @@ static int tcp_shifted_skb(struct sock *sk, struct sk_buff *skb,
|
|
tp->lost_cnt_hint -= tcp_skb_pcount(prev);
|
|
}
|
|
|
|
- TCP_SKB_CB(skb)->tcp_flags |= TCP_SKB_CB(prev)->tcp_flags;
|
|
+ TCP_SKB_CB(prev)->tcp_flags |= TCP_SKB_CB(skb)->tcp_flags;
|
|
+ if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN)
|
|
+ TCP_SKB_CB(prev)->end_seq++;
|
|
+
|
|
if (skb == tcp_highest_sack(sk))
|
|
tcp_advance_highest_sack(sk, skb);
|
|
|
|
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
|
|
index 12999a3aaf95..987f5cc706b4 100644
|
|
--- a/net/ipv4/tcp_output.c
|
|
+++ b/net/ipv4/tcp_output.c
|
|
@@ -933,6 +933,9 @@ static void tcp_queue_skb(struct sock *sk, struct sk_buff *skb)
|
|
static void tcp_set_skb_tso_segs(const struct sock *sk, struct sk_buff *skb,
|
|
unsigned int mss_now)
|
|
{
|
|
+ /* Make sure we own this skb before messing gso_size/gso_segs */
|
|
+ WARN_ON_ONCE(skb_cloned(skb));
|
|
+
|
|
if (skb->len <= mss_now || !sk_can_gso(sk) ||
|
|
skb->ip_summed == CHECKSUM_NONE) {
|
|
/* Avoid the costly divide in the normal
|
|
@@ -1014,9 +1017,7 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len,
|
|
if (nsize < 0)
|
|
nsize = 0;
|
|
|
|
- if (skb_cloned(skb) &&
|
|
- skb_is_nonlinear(skb) &&
|
|
- pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
|
|
+ if (skb_unclone(skb, GFP_ATOMIC))
|
|
return -ENOMEM;
|
|
|
|
/* Get a new skb... force flag on. */
|
|
@@ -2129,6 +2130,8 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
|
|
int oldpcount = tcp_skb_pcount(skb);
|
|
|
|
if (unlikely(oldpcount > 1)) {
|
|
+ if (skb_unclone(skb, GFP_ATOMIC))
|
|
+ return -ENOMEM;
|
|
tcp_init_tso_segs(sk, skb, cur_mss);
|
|
tcp_adjust_pcount(sk, skb, oldpcount - tcp_skb_pcount(skb));
|
|
}
|
|
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
|
|
index 73f1a00a96af..e38290b7c7a1 100644
|
|
--- a/net/ipv6/inet6_hashtables.c
|
|
+++ b/net/ipv6/inet6_hashtables.c
|
|
@@ -110,7 +110,7 @@ begintw:
|
|
goto out;
|
|
}
|
|
if (!INET6_TW_MATCH(sk, net, hash, saddr, daddr, ports, dif)) {
|
|
- sock_put(sk);
|
|
+ inet_twsk_put(inet_twsk(sk));
|
|
goto begintw;
|
|
}
|
|
goto out;
|
|
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
|
|
index 1acfb19cb570..7dabea3a7125 100644
|
|
--- a/net/ipv6/ip6_output.c
|
|
+++ b/net/ipv6/ip6_output.c
|
|
@@ -1345,7 +1345,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
|
|
skb = skb_peek_tail(&sk->sk_write_queue);
|
|
cork->length += length;
|
|
if (((length > mtu) ||
|
|
- (skb && skb_is_gso(skb))) &&
|
|
+ (skb && skb_has_frags(skb))) &&
|
|
(sk->sk_protocol == IPPROTO_UDP) &&
|
|
(rt->dst.dev->features & NETIF_F_UFO)) {
|
|
err = ip6_ufo_append_data(sk, getfrag, from, length,
|
|
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
|
|
index 016ed7c22fc9..4f768a4c2907 100644
|
|
--- a/net/ipv6/route.c
|
|
+++ b/net/ipv6/route.c
|
|
@@ -818,7 +818,7 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort,
|
|
}
|
|
|
|
static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table, int oif,
|
|
- struct flowi6 *fl6, int flags)
|
|
+ struct flowi6 *fl6, int flags, bool input)
|
|
{
|
|
struct fib6_node *fn;
|
|
struct rt6_info *rt, *nrt;
|
|
@@ -826,8 +826,11 @@ static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
|
|
int attempts = 3;
|
|
int err;
|
|
int reachable = net->ipv6.devconf_all->forwarding ? 0 : RT6_LOOKUP_F_REACHABLE;
|
|
+ int local = RTF_NONEXTHOP;
|
|
|
|
strict |= flags & RT6_LOOKUP_F_IFACE;
|
|
+ if (input)
|
|
+ local |= RTF_LOCAL;
|
|
|
|
relookup:
|
|
read_lock_bh(&table->tb6_lock);
|
|
@@ -847,7 +850,7 @@ restart:
|
|
read_unlock_bh(&table->tb6_lock);
|
|
|
|
if (!dst_get_neighbour_noref_raw(&rt->dst) &&
|
|
- !(rt->rt6i_flags & (RTF_NONEXTHOP | RTF_LOCAL)))
|
|
+ !(rt->rt6i_flags & local))
|
|
nrt = rt6_alloc_cow(rt, &fl6->daddr, &fl6->saddr);
|
|
else if (!(rt->dst.flags & DST_HOST))
|
|
nrt = rt6_alloc_clone(rt, &fl6->daddr);
|
|
@@ -891,7 +894,7 @@ out2:
|
|
static struct rt6_info *ip6_pol_route_input(struct net *net, struct fib6_table *table,
|
|
struct flowi6 *fl6, int flags)
|
|
{
|
|
- return ip6_pol_route(net, table, fl6->flowi6_iif, fl6, flags);
|
|
+ return ip6_pol_route(net, table, fl6->flowi6_iif, fl6, flags, true);
|
|
}
|
|
|
|
static struct dst_entry *ip6_route_input_lookup(struct net *net,
|
|
@@ -924,7 +927,7 @@ void ip6_route_input(struct sk_buff *skb)
|
|
static struct rt6_info *ip6_pol_route_output(struct net *net, struct fib6_table *table,
|
|
struct flowi6 *fl6, int flags)
|
|
{
|
|
- return ip6_pol_route(net, table, fl6->flowi6_oif, fl6, flags);
|
|
+ return ip6_pol_route(net, table, fl6->flowi6_oif, fl6, flags, false);
|
|
}
|
|
|
|
struct dst_entry * ip6_route_output(struct net *net, const struct sock *sk,
|
|
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c
|
|
index b2982f4214d1..904bc098790d 100644
|
|
--- a/net/l2tp/l2tp_ppp.c
|
|
+++ b/net/l2tp/l2tp_ppp.c
|
|
@@ -357,7 +357,9 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh
|
|
goto error_put_sess_tun;
|
|
}
|
|
|
|
+ local_bh_disable();
|
|
l2tp_xmit_skb(session, skb, session->hdr_len);
|
|
+ local_bh_enable();
|
|
|
|
sock_put(ps->tunnel_sock);
|
|
sock_put(sk);
|
|
@@ -432,7 +434,9 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
|
|
skb->data[0] = ppph[0];
|
|
skb->data[1] = ppph[1];
|
|
|
|
+ local_bh_disable();
|
|
l2tp_xmit_skb(session, skb, session->hdr_len);
|
|
+ local_bh_enable();
|
|
|
|
sock_put(sk_tun);
|
|
sock_put(sk);
|
|
diff --git a/net/sctp/output.c b/net/sctp/output.c
|
|
index 32ba8d0e50e2..cf3e22c586a6 100644
|
|
--- a/net/sctp/output.c
|
|
+++ b/net/sctp/output.c
|
|
@@ -518,7 +518,8 @@ int sctp_packet_transmit(struct sctp_packet *packet)
|
|
* by CRC32-C as described in <draft-ietf-tsvwg-sctpcsum-02.txt>.
|
|
*/
|
|
if (!sctp_checksum_disable) {
|
|
- if (!(dst->dev->features & NETIF_F_SCTP_CSUM)) {
|
|
+ if (!(dst->dev->features & NETIF_F_SCTP_CSUM) ||
|
|
+ (dst_xfrm(dst) != NULL) || packet->ipfragok) {
|
|
__u32 crc32 = sctp_start_cksum((__u8 *)sh, cksum_buf_len);
|
|
|
|
/* 3) Put the resultant value into the checksum field in the
|
|
diff --git a/net/socket.c b/net/socket.c
|
|
index 47ce3ea44300..acc769562707 100644
|
|
--- a/net/socket.c
|
|
+++ b/net/socket.c
|
|
@@ -1899,6 +1899,16 @@ struct used_address {
|
|
unsigned int name_len;
|
|
};
|
|
|
|
+static int copy_msghdr_from_user(struct msghdr *kmsg,
|
|
+ struct msghdr __user *umsg)
|
|
+{
|
|
+ if (copy_from_user(kmsg, umsg, sizeof(struct msghdr)))
|
|
+ return -EFAULT;
|
|
+ if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
|
|
+ return -EINVAL;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
|
|
struct msghdr *msg_sys, unsigned flags,
|
|
struct used_address *used_address)
|
|
@@ -1917,8 +1927,11 @@ static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
|
|
if (MSG_CMSG_COMPAT & flags) {
|
|
if (get_compat_msghdr(msg_sys, msg_compat))
|
|
return -EFAULT;
|
|
- } else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr)))
|
|
- return -EFAULT;
|
|
+ } else {
|
|
+ err = copy_msghdr_from_user(msg_sys, msg);
|
|
+ if (err)
|
|
+ return err;
|
|
+ }
|
|
|
|
/* do not move before msg_sys is valid */
|
|
err = -EMSGSIZE;
|
|
@@ -2129,8 +2142,11 @@ static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
|
|
if (MSG_CMSG_COMPAT & flags) {
|
|
if (get_compat_msghdr(msg_sys, msg_compat))
|
|
return -EFAULT;
|
|
- } else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr)))
|
|
- return -EFAULT;
|
|
+ } else {
|
|
+ err = copy_msghdr_from_user(msg_sys, msg);
|
|
+ if (err)
|
|
+ return err;
|
|
+ }
|
|
|
|
err = -EMSGSIZE;
|
|
if (msg_sys->msg_iovlen > UIO_MAXIOV)
|
|
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
|
|
index c4821fd23b79..ed005b425a7c 100644
|
|
--- a/net/unix/af_unix.c
|
|
+++ b/net/unix/af_unix.c
|
|
@@ -1247,6 +1247,15 @@ static int unix_socketpair(struct socket *socka, struct socket *sockb)
|
|
return 0;
|
|
}
|
|
|
|
+static void unix_sock_inherit_flags(const struct socket *old,
|
|
+ struct socket *new)
|
|
+{
|
|
+ if (test_bit(SOCK_PASSCRED, &old->flags))
|
|
+ set_bit(SOCK_PASSCRED, &new->flags);
|
|
+ if (test_bit(SOCK_PASSSEC, &old->flags))
|
|
+ set_bit(SOCK_PASSSEC, &new->flags);
|
|
+}
|
|
+
|
|
static int unix_accept(struct socket *sock, struct socket *newsock, int flags)
|
|
{
|
|
struct sock *sk = sock->sk;
|
|
@@ -1281,6 +1290,7 @@ static int unix_accept(struct socket *sock, struct socket *newsock, int flags)
|
|
/* attach accepted sock to socket */
|
|
unix_state_lock(tsk);
|
|
newsock->state = SS_CONNECTED;
|
|
+ unix_sock_inherit_flags(sock, newsock);
|
|
sock_graft(tsk, newsock);
|
|
unix_state_unlock(tsk);
|
|
return 0;
|
|
diff --git a/net/unix/diag.c b/net/unix/diag.c
|
|
index f0486ae9ebe6..2656840cf203 100644
|
|
--- a/net/unix/diag.c
|
|
+++ b/net/unix/diag.c
|
|
@@ -134,6 +134,7 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct unix_diag_r
|
|
rep->udiag_family = AF_UNIX;
|
|
rep->udiag_type = sk->sk_type;
|
|
rep->udiag_state = sk->sk_state;
|
|
+ rep->pad = 0;
|
|
rep->udiag_ino = sk_ino;
|
|
sock_diag_save_cookie(sk, rep->udiag_cookie);
|
|
|
|
diff --git a/net/wireless/radiotap.c b/net/wireless/radiotap.c
|
|
index c4ad7958af52..617a310025b1 100644
|
|
--- a/net/wireless/radiotap.c
|
|
+++ b/net/wireless/radiotap.c
|
|
@@ -95,6 +95,10 @@ int ieee80211_radiotap_iterator_init(
|
|
struct ieee80211_radiotap_header *radiotap_header,
|
|
int max_length, const struct ieee80211_radiotap_vendor_namespaces *vns)
|
|
{
|
|
+ /* check the radiotap header can actually be present */
|
|
+ if (max_length < sizeof(struct ieee80211_radiotap_header))
|
|
+ return -EINVAL;
|
|
+
|
|
/* Linux only supports version 0 radiotap format */
|
|
if (radiotap_header->it_version)
|
|
return -EINVAL;
|
|
@@ -129,7 +133,8 @@ int ieee80211_radiotap_iterator_init(
|
|
*/
|
|
|
|
if ((unsigned long)iterator->_arg -
|
|
- (unsigned long)iterator->_rtheader >
|
|
+ (unsigned long)iterator->_rtheader +
|
|
+ sizeof(uint32_t) >
|
|
(unsigned long)iterator->_max_length)
|
|
return -EINVAL;
|
|
}
|