* Re: regression when connecting to ipv6 localhost
From: Jan Hinnerk Stosch @ 2012-10-15 13:28 UTC (permalink / raw)
To: Eric Dumazet; +Cc: netdev
In-Reply-To: <1350307293.3954.119.camel@edumazet-glaptop>
[-- Attachment #1: Type: text/plain, Size: 158 bytes --]
2012/10/15 Eric Dumazet <eric.dumazet@gmail.com>:
>
> OK thanks
>
> Now we have to find why ::1 is missing.
>
> Can you send :
>
> lsmod
>
>
Yes. Attached..
[-- Attachment #2: lsmod --]
[-- Type: application/octet-stream, Size: 3835 bytes --]
Module Size Used by
fuse 69173 3
saa7134_alsa 10878 0
tda1004x 15485 1
saa7134_dvb 25964 0
videobuf_dvb 4890 1 saa7134_dvb
dvb_core 96168 1 videobuf_dvb
lm75 4312 0
it87 29819 0
hwmon_vid 3196 1 it87
iTCO_wdt 5255 0
iTCO_vendor_support 1929 1 iTCO_wdt
snd_hda_codec_hdmi 24487 1
snd_hda_codec_realtek 61033 1
hid_logitech_dj 10189 0
joydev 9991 0
tda827x 9558 2
hid_cherry 1577 0
usbhid 36996 1 hid_logitech_dj
hid 85929 3 hid_cherry,usbhid,hid_logitech_dj
tda8290 12682 1
tuner 16843 1
usb_storage 47320 1
uas 11119 0
microcode 12377 0
aesni_intel 42081 0
aes_x86_64 7508 1 aesni_intel
aes_generic 26138 2 aesni_intel,aes_x86_64
ablk_helper 1972 1 aesni_intel
ghash_clmulni_intel 4237 0
cryptd 8741 3 ghash_clmulni_intel,aesni_intel,ablk_helper
kvm_intel 124749 0
kvm 373949 1 kvm_intel
coretemp 5974 0
crc32c_intel 1987 0
saa7134 168976 2 saa7134_dvb,saa7134_alsa
tveeprom 13777 1 saa7134
videobuf_dma_sg 7872 3 saa7134_dvb,saa7134,saa7134_alsa
psmouse 71909 0
videobuf_core 16007 3 videobuf_dma_sg,saa7134,videobuf_dvb
v4l2_common 5370 2 tuner,saa7134
videodev 100859 3 tuner,saa7134,v4l2_common
serio_raw 4689 0
media 10405 1 videodev
rc_core 13088 1 saa7134
i2c_i801 9571 0
pcspkr 1899 0
lpc_ich 10609 0
snd_hda_intel 26180 1
snd_hda_codec 98033 3 snd_hda_codec_realtek,snd_hda_codec_hdmi,snd_hda_intel
atl1c 33646 0
snd_hwdep 6300 1 snd_hda_codec
snd_pcm 75167 4 snd_hda_codec_hdmi,snd_hda_codec,snd_hda_intel,saa7134_alsa
snd_page_alloc 7217 2 snd_pcm,snd_hda_intel
snd_timer 18934 1 snd_pcm
snd 59989 10 snd_hda_codec_realtek,snd_hwdep,snd_timer,snd_hda_codec_hdmi,snd_pcm,snd_hda_codec,snd_hda_intel,saa7134_alsa
soundcore 5442 1 snd
mei 32665 0
acpi_cpufreq 5933 0
mperf 1267 1 acpi_cpufreq
evdev 10266 9
fan 2618 0
processor 26855 1 acpi_cpufreq
thermal 8119 0
ext4 440093 3
crc16 1359 1 ext4
jbd2 78751 1 ext4
mbcache 5977 1 ext4
sr_mod 14823 0
sd_mod 29559 6
cdrom 35520 1 sr_mod
ahci 21360 3
libahci 20023 1 ahci
xhci_hcd 86922 0
libata 167683 2 ahci,libahci
ehci_hcd 41816 0
scsi_mod 133386 5 uas,usb_storage,libata,sd_mod,sr_mod
usbcore 150334 5 uas,usb_storage,ehci_hcd,usbhid,xhci_hcd
usb_common 954 1 usbcore
i915 495105 2
video 11276 1 i915
button 4662 1 i915
i2c_algo_bit 5391 1 i915
intel_agp 10744 1 i915
intel_gtt 15659 2 i915,intel_agp
drm_kms_helper 32877 1 i915
drm 218724 3 i915,drm_kms_helper
i2c_core 20707 15 drm,i915,lm75,i2c_i801,tuner,saa7134_dvb,saa7134,drm_kms_helper,tda8290,tda827x,i2c_algo_bit,v4l2_common,tveeprom,tda1004x,videodev
^ permalink raw reply
* [PATCH] sctp: fix call to SCTP_CMD_PROCESS_SACK in sctp_cmd_interpreter()
From: nicolas.dichtel @ 2012-10-15 13:56 UTC (permalink / raw)
To: linux-sctp, vyasevich; +Cc: netdev, Zijie Pan, Nicolas Dichtel
From: Zijie Pan <zijie.pan@6wind.com>
Bug introduced by commit edfee0339e681a784ebacec7e8c2dc97dc6d2839
(sctp: check src addr when processing SACK to update transport state)
Signed-off-by: Zijie Pan <zijie.pan@6wind.com>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
net/sctp/sm_sideeffect.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index 57f7de8..6773d78 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -1642,8 +1642,9 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
asoc->outqueue.outstanding_bytes;
sackh.num_gap_ack_blocks = 0;
sackh.num_dup_tsns = 0;
+ chunk->subh.sack_hdr = &sackh;
sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_SACK,
- SCTP_SACKH(&sackh));
+ SCTP_CHUNK(chunk));
break;
case SCTP_CMD_DISCARD_PACKET:
--
1.7.12
^ permalink raw reply related
* [PATCH] net dsa: add new option "master_netdev_autoup"
From: Rodolfo Giometti @ 2012-10-15 13:33 UTC (permalink / raw)
To: netdev; +Cc: Lennert Buytenhek, Rodolfo Giometti
In-Reply-To: <1350308008-17189-1-git-send-email-giometti@linux.it>
By using this option the user can decide if the master device should
be turned on when one of the slave devices is opened.
This functionality is needed if RootFS over NFS is used throught the
DSA.
Signed-off-by: Rodolfo Giometti <giometti@linux.it>
---
include/net/dsa.h | 8 ++++++++
net/dsa/slave.c | 7 ++++++-
2 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/include/net/dsa.h b/include/net/dsa.h
index ff07a86..bd3c8b8 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -63,6 +63,14 @@ struct dsa_platform_data {
struct device *netdev;
/*
+ * Enable the auto-up of the master device when a slave is
+ * open.
+ * This functionality is needed if RootFS over NFS is used
+ * throught the DSA.
+ */
+ unsigned long master_netdev_autoup:1;
+
+ /*
* Info structs describing each of the switch chips
* connected via this network interface.
*/
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 4286964..6e9e4546 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -66,9 +66,14 @@ static int dsa_slave_open(struct net_device *dev)
{
struct dsa_slave_priv *p = netdev_priv(dev);
struct net_device *master = p->parent->dst->master_netdev;
+ struct dsa_platform_data *pd = p->parent->dst->pd;
int err;
- if (!(master->flags & IFF_UP))
+ if (pd->master_netdev_autoup)
+ err = dev_open(master);
+ else
+ err = !(master->flags & IFF_UP);
+ if (err)
return -ENETDOWN;
if (!ether_addr_equal(dev->dev_addr, master->dev_addr)) {
--
1.7.9.5
^ permalink raw reply related
* [PATCH] net dsa: add per port phy address mapping
From: Rodolfo Giometti @ 2012-10-15 13:33 UTC (permalink / raw)
To: netdev; +Cc: Lennert Buytenhek, Rodolfo Giometti
In some circumstances ports' phy addresses must be remapped in a custom
manner (i.e. when phys have multiple MDIO addresses).
Compatibility with old behaviour is kept by using a special flag named
"port_phy_remap" which must be set to 1 in order to enable remapping
defined into "port_phy_addr" array.
Signed-off-by: Rodolfo Giometti <giometti@linux.it>
---
include/net/dsa.h | 11 +++++++++++
net/dsa/dsa.c | 3 ++-
net/dsa/dsa_priv.h | 3 ++-
net/dsa/slave.c | 25 +++++++++++++++----------
4 files changed, 30 insertions(+), 12 deletions(-)
diff --git a/include/net/dsa.h b/include/net/dsa.h
index 7828ebf..ff07a86 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -36,6 +36,17 @@ struct dsa_chip_data {
char *port_names[DSA_MAX_PORTS];
/*
+ * The MDIO address of the phy connected to each port.
+ * Set port_phy_remap = 1 in order to activate the remap otherwise
+ * is assumed that phy on port0 has address 0x0, phy on port1 has
+ * address 0x1 and so on...
+ * Note that for ports marked as "cpu" or "dsa" these fields are
+ * ignored.
+ */
+ unsigned long port_phy_remap:1;
+ int port_phy_addr[DSA_MAX_PORTS];
+
+ /*
* An array (with nr_chips elements) of which element [a]
* indicates which port on this switch should be used to
* send packets to that are destined for switch a. Can be
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 88e7c2f..a7f6fa2 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -175,7 +175,8 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
if (!(ds->phys_port_mask & (1 << i)))
continue;
- slave_dev = dsa_slave_create(ds, parent, i, pd->port_names[i]);
+ slave_dev = dsa_slave_create(ds, parent, i, pd->port_names[i],
+ pd->port_phy_remap ? pd->port_phy_addr[i] : i);
if (slave_dev == NULL) {
printk(KERN_ERR "%s[%d]: can't create dsa "
"slave device for port %d(%s)\n",
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index d4cf5cc..7bf1876 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -42,7 +42,8 @@ extern char dsa_driver_version[];
void dsa_slave_mii_bus_init(struct dsa_switch *ds);
struct net_device *dsa_slave_create(struct dsa_switch *ds,
struct device *parent,
- int port, char *name);
+ int port, char *name,
+ int phy_addr);
/* tag_dsa.c */
netdev_tx_t dsa_xmit(struct sk_buff *skb, struct net_device *dev);
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index e32083d..4286964 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -19,20 +19,25 @@ static int dsa_slave_phy_read(struct mii_bus *bus, int addr, int reg)
{
struct dsa_switch *ds = bus->priv;
- if (ds->phys_port_mask & (1 << addr))
- return ds->drv->phy_read(ds, addr, reg);
-
- return 0xffff;
+ /*
+ * if port_phy_remap is not enabled when can use old sanity check:
+ *
+ * if (ds->phys_port_mask & (1 << port))
+ *
+ * but if port_phy_remap is enabled we should find port<-->addr
+ * mapping by looking into port_phy_addr array... that why I dropped
+ * any sanity checks here (real kernel programmers should know what
+ * they do! ;) - Rodolfo Giometti
+ */
+ return ds->drv->phy_read(ds, addr, reg);
}
static int dsa_slave_phy_write(struct mii_bus *bus, int addr, int reg, u16 val)
{
struct dsa_switch *ds = bus->priv;
- if (ds->phys_port_mask & (1 << addr))
- return ds->drv->phy_write(ds, addr, reg, val);
-
- return 0;
+ /* See comment in function dsa_slave_phy_read() above */
+ return ds->drv->phy_write(ds, addr, reg, val);
}
void dsa_slave_mii_bus_init(struct dsa_switch *ds)
@@ -333,7 +338,7 @@ static const struct net_device_ops trailer_netdev_ops = {
/* slave device setup *******************************************************/
struct net_device *
dsa_slave_create(struct dsa_switch *ds, struct device *parent,
- int port, char *name)
+ int port, char *name, int phy_addr)
{
struct net_device *master = ds->dst->master_netdev;
struct net_device *slave_dev;
@@ -377,7 +382,7 @@ dsa_slave_create(struct dsa_switch *ds, struct device *parent,
p->dev = slave_dev;
p->parent = ds;
p->port = port;
- p->phy = ds->slave_mii_bus->phy_map[port];
+ p->phy = ds->slave_mii_bus->phy_map[phy_addr];
ret = register_netdev(slave_dev);
if (ret) {
--
1.7.9.5
^ permalink raw reply related
* [PATCH] net dsa: add phy's interrupts management
From: Rodolfo Giometti @ 2012-10-15 13:33 UTC (permalink / raw)
To: netdev; +Cc: Lennert Buytenhek, Rodolfo Giometti
In-Reply-To: <1350308008-17189-1-git-send-email-giometti@linux.it>
Signed-off-by: Rodolfo Giometti <giometti@linux.it>
---
net/dsa/slave.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 6e9e4546..817bbbd 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -340,6 +340,11 @@ static const struct net_device_ops trailer_netdev_ops = {
};
#endif
+static void dsa_slave_handle_link_change(struct net_device *dev)
+{
+ /* nop */
+}
+
/* slave device setup *******************************************************/
struct net_device *
dsa_slave_create(struct dsa_switch *ds, struct device *parent,
@@ -400,8 +405,8 @@ dsa_slave_create(struct dsa_switch *ds, struct device *parent,
netif_carrier_off(slave_dev);
if (p->phy != NULL) {
- phy_attach(slave_dev, dev_name(&p->phy->dev),
- 0, PHY_INTERFACE_MODE_GMII);
+ phy_connect_direct(p->dev, p->phy, dsa_slave_handle_link_change,
+ 0, PHY_INTERFACE_MODE_GMII);
p->phy->autoneg = AUTONEG_ENABLE;
p->phy->speed = 0;
--
1.7.9.5
^ permalink raw reply related
* [PATCH] net dsa: add TX timestamping support
From: Rodolfo Giometti @ 2012-10-15 13:33 UTC (permalink / raw)
To: netdev; +Cc: Lennert Buytenhek, Rodolfo Giometti
In-Reply-To: <1350308008-17189-1-git-send-email-giometti@linux.it>
Signed-off-by: Rodolfo Giometti <giometti@linux.it>
---
net/dsa/tag_dsa.c | 8 ++++++++
net/dsa/tag_edsa.c | 8 ++++++++
net/dsa/tag_trailer.c | 8 ++++++++
3 files changed, 24 insertions(+)
diff --git a/net/dsa/tag_dsa.c b/net/dsa/tag_dsa.c
index cacce1e..20c2959 100644
--- a/net/dsa/tag_dsa.c
+++ b/net/dsa/tag_dsa.c
@@ -24,6 +24,14 @@ netdev_tx_t dsa_xmit(struct sk_buff *skb, struct net_device *dev)
dev->stats.tx_packets++;
dev->stats.tx_bytes += skb->len;
+ /* We should call skb_tx_timestamp() at bottom of this function,
+ * just before dev_queue_xmit(), but the skb is going to be
+ * modified by DSA stack so it is going to be NOT recognized
+ * by the ptp_filter called into function skb_clone_tx_timestamp()
+ * [see file linux/net/core/timestamping.c].
+ */
+ skb_tx_timestamp(skb);
+
/*
* Convert the outermost 802.1q tag to a DSA tag for tagged
* packets, or insert a DSA tag between the addresses and
diff --git a/net/dsa/tag_edsa.c b/net/dsa/tag_edsa.c
index e70c43c..9138bda 100644
--- a/net/dsa/tag_edsa.c
+++ b/net/dsa/tag_edsa.c
@@ -25,6 +25,14 @@ netdev_tx_t edsa_xmit(struct sk_buff *skb, struct net_device *dev)
dev->stats.tx_packets++;
dev->stats.tx_bytes += skb->len;
+ /* We should call skb_tx_timestamp() at bottom of this function,
+ * just before dev_queue_xmit(), but the skb is going to be
+ * modified by DSA stack so it is going to be NOT recognized
+ * by the ptp_filter called into function skb_clone_tx_timestamp()
+ * [see file linux/net/core/timestamping.c].
+ */
+ skb_tx_timestamp(skb);
+
/*
* Convert the outermost 802.1q tag to a DSA tag and prepend
* a DSA ethertype field is the packet is tagged, or insert
diff --git a/net/dsa/tag_trailer.c b/net/dsa/tag_trailer.c
index 94bc260..b92cad2 100644
--- a/net/dsa/tag_trailer.c
+++ b/net/dsa/tag_trailer.c
@@ -24,6 +24,14 @@ netdev_tx_t trailer_xmit(struct sk_buff *skb, struct net_device *dev)
dev->stats.tx_packets++;
dev->stats.tx_bytes += skb->len;
+ /* We should call skb_tx_timestamp() at bottom of this function,
+ * just before dev_queue_xmit(), but the skb is going to be
+ * modified by DSA stack so it is going to be NOT recognized
+ * by the ptp_filter called into function skb_clone_tx_timestamp()
+ * [see file linux/net/core/timestamping.c].
+ */
+ skb_tx_timestamp(skb);
+
/*
* We have to make sure that the trailer ends up as the very
* last 4 bytes of the packet. This means that we have to pad
--
1.7.9.5
^ permalink raw reply related
* Re: [PATCH 01/12] usbnet: introduce usbnet 3 command helpers
From: Alan Stern @ 2012-10-15 14:27 UTC (permalink / raw)
To: Oliver Neukum
Cc: Ming Lei, David S. Miller, Greg Kroah-Hartman,
netdev-u79uwXL29TY76Z2rM5mHXA, linux-usb-u79uwXL29TY76Z2rM5mHXA,
jkosina-IBi9RG/b67k
In-Reply-To: <15188898.QK0YCDZ0MW-ugxBuEnWX9yG/4A2pS7c2Q@public.gmane.org>
On Mon, 15 Oct 2012, Oliver Neukum wrote:
> On Friday 12 October 2012 11:29:49 Alan Stern wrote:
> > On Fri, 12 Oct 2012, Oliver Neukum wrote:
>
> > > First we have workqueues. bas-gigaset is a good example.
> > > The driver kills a scheduled work in pre_reset(). If this is done synchronously
> > > the driver may need to wait for a memory allocation inside the work.
> > > In principle we could provide a workqueue limited to GFP_NOIO. Is that worth
> > > it, or do we just check?
> >
> > The work routine could set the GFP mask upon entry and exit. Then a
> > separate workqueue wouldn't be needed.
>
> Well, yes. But if we have to touch the code we might just as well use GFP-NOIO
Depends on what the code does. If it does very little requiring memory
allocation then yes, you could simply use GFP_NOIO. But if it calls
lots of other routines that all do their own allocation, setting the
mask will be better.
> > > I am afraid there is no generic solution in the last two cases. What do you think?
> >
> > The other contexts must also set the GFP mask. Unfortunately, this has
> > to be done case-by-case.
>
> This raises a question. If we do the port-power-off stuff, does reset_resume() of every
> device under the depowered port have to be called?
Certainly.
> If so, we cannot exclude vendor
> specific drivers from the audit, can we?
True. But hasn't that always been the case? A device could need a
vendor-specific driver for one interface while another interface uses a
standard mass-storage protocol.
Alan Stern
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Payment Sent!!
From: Western Union Transfer @ 2012-10-15 5:50 UTC (permalink / raw)
To: netdev
We write to inform you that we have transferred $400,000 dollars. deposited for transfer to you by one MR Bernard Harry from BLACKBERRY MOBILE COMPANY for transfer as a winning prize from the promotion lottery held by the communication company to encourage usage and appreciate already users of their product.
The money is available for pick up by receiver(you) to be cashed on daily installment of $10,000 for 40days. We tried calling to give you the information over the phone but we could not reach you so we decided to email you the information to pick up the first $10,000 already transferred to you in your name. Please take the below information alongside with a valid identity card and rush off to any western union office close to and pick up the $10,000 within the next 10hours and get back to us after picking up the first $10,000, for you to be able to pick the first payment,
You will have to pay $250 to get it re-activated in your name for you to start picking up your money.
Use this link to track the below information
https://wumt.westernunion.com/asp/orderStatus.asp?country=global
Sender's Fist name: Daniel
Sender's Last Name: Williams
MTCN: 3549027839
Question: Who Is Great
Answer: God
Amount: $10,000.00USD
Thanks
Best Regards
Mr.Mcferrin Phoenix .
+60169162934
western union Office,
MALAYSIA OFFICE.
Western Union® Money Transfer
^ permalink raw reply
* Re: [patch net] vlan: fix bond/team enslave of vlan challenged slave/port
From: Jon Stanley @ 2012-10-15 14:53 UTC (permalink / raw)
To: Jiri Pirko; +Cc: netdev, davem, fubar, andy, kaber
In-Reply-To: <1350225056-14144-1-git-send-email-jiri@resnulli.us>
On Sun, Oct 14, 2012 at 10:30 AM, Jiri Pirko <jiri@resnulli.us> wrote:
> In vlan_uses_dev() check for number of vlan devs rather than existence
> of vlan_info. The reason is that vlan id 0 is there without appropriate
> vlan dev on it by default which prevented from enslaving vlan challenged
> dev.
Thanks for the patch!
However, I'm now running into a new issue. Note that I've backported
this to an older kernel (3.3.2, eww), but I don't *think* that matters
for this. Now I'm getting a "refused to change device type" which
looks like it comes from around here:
res = netdev_bonding_change(bond_dev,
NETDEV_PRE_TYPE_CHANGE);
res = notifier_to_errno(res);
if (res) {
pr_err("%s: refused to change device type\n",
bond_dev->name);
I'm not quite smart enough to figure out what's going on here. FWIW,
looking back in history it looks like the only relevant change from
here to mainline is the replacement of netdev_bonding_change() with
direct calls to call_netdevice_notifiers().
Again, .let me know if more info is needed, and thanks for the quick response!
^ permalink raw reply
* Re: [PATCH] sctp: fix call to SCTP_CMD_PROCESS_SACK in sctp_cmd_interpreter()
From: Vlad Yasevich @ 2012-10-15 15:40 UTC (permalink / raw)
To: nicolas.dichtel; +Cc: linux-sctp, netdev, Zijie Pan
In-Reply-To: <1350309399-23422-1-git-send-email-nicolas.dichtel@6wind.com>
On 10/15/2012 09:56 AM, nicolas.dichtel@6wind.com wrote:
> From: Zijie Pan <zijie.pan@6wind.com>
>
> Bug introduced by commit edfee0339e681a784ebacec7e8c2dc97dc6d2839
> (sctp: check src addr when processing SACK to update transport state)
>
> Signed-off-by: Zijie Pan <zijie.pan@6wind.com>
> Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Shutdown case.. ACK.
Acked-by: Vlad Yasevich <vyasevich@gmail.com>
> ---
> net/sctp/sm_sideeffect.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
> index 57f7de8..6773d78 100644
> --- a/net/sctp/sm_sideeffect.c
> +++ b/net/sctp/sm_sideeffect.c
> @@ -1642,8 +1642,9 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
> asoc->outqueue.outstanding_bytes;
> sackh.num_gap_ack_blocks = 0;
> sackh.num_dup_tsns = 0;
> + chunk->subh.sack_hdr = &sackh;
> sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_SACK,
> - SCTP_SACKH(&sackh));
> + SCTP_CHUNK(chunk));
> break;
>
> case SCTP_CMD_DISCARD_PACKET:
>
^ permalink raw reply
* Re: [PATCH] sock filter: fix copy of filter from userspace
From: Stephen Hemminger @ 2012-10-15 15:57 UTC (permalink / raw)
To: Jiri Pirko; +Cc: Jiri Pirko, David S. Miller, netdev
In-Reply-To: <20121013191949.GA16286@minipsycho.orion>
On Sat, 13 Oct 2012 21:19:49 +0200
Jiri Pirko <jiri@resnulli.us> wrote:
> Sat, Oct 13, 2012 at 08:40:32PM CEST, shemminger@vyatta.com wrote:
> >The sk_unattached_filter_create function is passed a socket
> >filter structure and the copies the contents of the filter from
> >userspace. Sparse detected that this code was incorrectly using
> >memcpy when it needed to use copy_from_user instead.
>
> Hmm. fprog->filter is in this case allocated and filled in kernel.
> So memcpy is good.
>
> Not sure how to handle this correctly. Either we remove "__user" or we
> redefine "struct sock_fprog" for sk_unattached_filter_create() use.
>
> Any thoughts?
Or define a different structure for kernel usage versus userspace API.
^ permalink raw reply
* [PATCH v6 00/10] IPC: checkpoint/restore in userspace enhancements
From: Stanislav Kinsbursky @ 2012-10-15 15:59 UTC (permalink / raw)
To: akpm
Cc: catalin.marinas, will.deacon, dhowells, manfred, hughd, jmorris,
mtk.manpages, kosaki.motohiro, paulmck, sds, devel, a.p.zijlstra,
cmetcalf, linux-driver, ron.mercer, viro, eparis, tglx,
jitendra.kalsaria, netdev, linux-kernel, linux-security-module,
ebiederm, casey
v6:
1) rebased on 3.7-rc1
v5:
1) Several define-dependent compile bugs fixed
2) IPC message copy test updated
3) A couple of minor fixes.
4) Qlogic driver update: rename of its internal SEM_SET define into SEM_INIT
(compile error).
v4:
1) If MSG_COPY flag is specified, then "mtype" is not a type, but message
number to copy.
2) MSG_SET_COPY logic for sys_msgctl() was removed.
v3:
1) Copy messages to user-space under spinlock was replaced by allocation of
dummy message before queue lock and then copy of desired message to the dummy
one instead of unlinking it from queue list.
I.e. the message queue copy logic was changed: messages can be retrived one by
one (instead of receiving of the whole list at once).
This patch set is aimed to provide additional functionality for all IPC
objects,
which is required for migration of these objects by user-space
checkpoint/restore utils (CRIU).
The main problem here was impossibility to set up object id. This patch set
solves the problem in two steps:
1) Makes it possible to create new object (shared memory, semaphores set or
messages queue) with ID, equal to passed key.
2) Makes it possible to change existent object key.
Another problem was to peek messages from queues without deleting them.
This was achived by introducing of new MSG_COPY flag for sys_msgrcv(). If
MSG_COPY flag is set, then msgtyp is interpreted as message number.
The following series implements...
---
Stanislav Kinsbursky (10):
ipc: remove forced assignment of selected message
ipc: "use key as id" functionality for resource get system call introduced
ipc: segment key change helper introduced
ipc: add new SHM_SET command for sys_shmctl() call
ipc: add new MSG_SET command for sys_msgctl() call
glge driver: rename internal SEM_SET macro to SEM_INIT
ipc: add new SEM_SET command for sys_semctl() call
IPC: message queue receive cleanup
IPC: message queue copy feature introduced
test: IPC message queue copy feture test
drivers/net/ethernet/qlogic/qlge/qlge.h | 4
drivers/net/ethernet/qlogic/qlge/qlge_main.c | 16 +-
include/linux/msg.h | 5 -
include/uapi/linux/ipc.h | 1
include/uapi/linux/msg.h | 2
include/uapi/linux/sem.h | 1
include/uapi/linux/shm.h | 1
ipc/compat.c | 45 +++--
ipc/msg.c | 116 +++++++++---
ipc/msgutil.c | 38 ++++
ipc/sem.c | 14 +
ipc/shm.c | 17 +-
ipc/util.c | 69 +++++++
ipc/util.h | 6 +
security/selinux/hooks.c | 3
security/smack/smack_lsm.c | 3
tools/testing/selftests/ipc/Makefile | 28 +++
tools/testing/selftests/ipc/msgque.c | 251 ++++++++++++++++++++++++++
18 files changed, 548 insertions(+), 72 deletions(-)
create mode 100644 tools/testing/selftests/ipc/Makefile
create mode 100644 tools/testing/selftests/ipc/msgque.c
^ permalink raw reply
* [PATCH v6 01/10] ipc: remove forced assignment of selected message
From: Stanislav Kinsbursky @ 2012-10-15 15:59 UTC (permalink / raw)
To: akpm
Cc: catalin.marinas, will.deacon, dhowells, manfred, hughd, jmorris,
mtk.manpages, kosaki.motohiro, paulmck, sds, devel, a.p.zijlstra,
cmetcalf, linux-driver, ron.mercer, viro, eparis, tglx,
jitendra.kalsaria, netdev, linux-kernel, linux-security-module,
ebiederm, casey
In-Reply-To: <20121015155800.28348.23561.stgit@localhost.localdomain>
This is a cleanup patch. The assignment is redundant.
Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
---
ipc/msg.c | 5 +----
1 files changed, 1 insertions(+), 4 deletions(-)
diff --git a/ipc/msg.c b/ipc/msg.c
index a71af5a..2f272fa 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -793,12 +793,9 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext,
msg = walk_msg;
if (mode == SEARCH_LESSEQUAL &&
walk_msg->m_type != 1) {
- msg = walk_msg;
msgtyp = walk_msg->m_type - 1;
- } else {
- msg = walk_msg;
+ } else
break;
- }
}
tmp = tmp->next;
}
^ permalink raw reply related
* [PATCH v6 02/10] ipc: "use key as id" functionality for resource get system call introduced
From: Stanislav Kinsbursky @ 2012-10-15 15:59 UTC (permalink / raw)
To: akpm
Cc: catalin.marinas, will.deacon, dhowells, manfred, hughd, jmorris,
mtk.manpages, kosaki.motohiro, paulmck, sds, devel, a.p.zijlstra,
cmetcalf, linux-driver, ron.mercer, viro, eparis, tglx,
jitendra.kalsaria, netdev, linux-kernel, linux-security-module,
ebiederm, casey
In-Reply-To: <20121015155800.28348.23561.stgit@localhost.localdomain>
This patch introduces new IPC resource get request flag IPC_PRESET, which
should be interpreted as a request to try to allocate IPC slot with number,
starting from value resented by key. IOW, kernel will try
allocate new segment in specified slot.
Note: if desired slot is not emply, then next free slot will be used.
Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
---
include/uapi/linux/ipc.h | 1 +
ipc/msg.c | 4 +++-
ipc/sem.c | 4 +++-
ipc/shm.c | 4 +++-
ipc/util.c | 18 +++++++++++++++---
ipc/util.h | 3 ++-
6 files changed, 27 insertions(+), 7 deletions(-)
diff --git a/include/uapi/linux/ipc.h b/include/uapi/linux/ipc.h
index de08dd4..f5f52b6 100644
--- a/include/uapi/linux/ipc.h
+++ b/include/uapi/linux/ipc.h
@@ -24,6 +24,7 @@ struct ipc_perm
#define IPC_CREAT 00001000 /* create if key is nonexistent */
#define IPC_EXCL 00002000 /* fail if key exists */
#define IPC_NOWAIT 00004000 /* return error on wait */
+#define IPC_PRESET 00040000 /* use key as id */
/* these fields are used by the DIPC package so the kernel as standard
should avoid using them if possible */
diff --git a/ipc/msg.c b/ipc/msg.c
index 2f272fa..2f44946 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -190,6 +190,7 @@ static int newque(struct ipc_namespace *ns, struct ipc_params *params)
msq->q_perm.mode = msgflg & S_IRWXUGO;
msq->q_perm.key = key;
+ msq->q_perm.id = (msgflg & IPC_PRESET) ? key : 0;
msq->q_perm.security = NULL;
retval = security_msg_queue_alloc(msq);
@@ -201,7 +202,8 @@ static int newque(struct ipc_namespace *ns, struct ipc_params *params)
/*
* ipc_addid() locks msq
*/
- id = ipc_addid(&msg_ids(ns), &msq->q_perm, ns->msg_ctlmni);
+ id = ipc_addid(&msg_ids(ns), &msq->q_perm, ns->msg_ctlmni,
+ msgflg & IPC_PRESET);
if (id < 0) {
security_msg_queue_free(msq);
ipc_rcu_putref(msq);
diff --git a/ipc/sem.c b/ipc/sem.c
index 58d31f1..10e9085 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -306,6 +306,7 @@ static int newary(struct ipc_namespace *ns, struct ipc_params *params)
sma->sem_perm.mode = (semflg & S_IRWXUGO);
sma->sem_perm.key = key;
+ sma->sem_perm.id = (semflg & IPC_PRESET) ? key : 0;
sma->sem_perm.security = NULL;
retval = security_sem_alloc(sma);
@@ -314,7 +315,8 @@ static int newary(struct ipc_namespace *ns, struct ipc_params *params)
return retval;
}
- id = ipc_addid(&sem_ids(ns), &sma->sem_perm, ns->sc_semmni);
+ id = ipc_addid(&sem_ids(ns), &sma->sem_perm, ns->sc_semmni,
+ semflg & IPC_PRESET);
if (id < 0) {
security_sem_free(sma);
ipc_rcu_putref(sma);
diff --git a/ipc/shm.c b/ipc/shm.c
index dff40c9..80b0046 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -480,6 +480,7 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
shp->shm_perm.key = key;
shp->shm_perm.mode = (shmflg & S_IRWXUGO);
+ shp->shm_perm.id = (shmflg & IPC_PRESET) ? key : 0;
shp->mlock_user = NULL;
shp->shm_perm.security = NULL;
@@ -510,7 +511,8 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
if (IS_ERR(file))
goto no_file;
- id = ipc_addid(&shm_ids(ns), &shp->shm_perm, ns->shm_ctlmni);
+ id = ipc_addid(&shm_ids(ns), &shp->shm_perm, ns->shm_ctlmni,
+ shmflg & IPC_PRESET);
if (id < 0) {
error = id;
goto no_id;
diff --git a/ipc/util.c b/ipc/util.c
index 72fd078..503946e 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -238,16 +238,22 @@ int ipc_get_maxid(struct ipc_ids *ids)
* @ids: IPC identifier set
* @new: new IPC permission set
* @size: limit for the number of used ids
+ * @preset: use passed new->id value as desired id
*
* Add an entry 'new' to the IPC ids idr. The permissions object is
* initialised and the first free entry is set up and the id assigned
* is returned. The 'new' entry is returned in a locked state on success.
* On failure the entry is not locked and a negative err-code is returned.
*
+ * If 'preset' is set, then passed new->id is desired to be set for new
+ * segment. And allocated id is equal to passed value, then ipc ids will
+ * left unchanged and new->seq will be updated to correspond specified id value.
+ *
* Called with ipc_ids.rw_mutex held as a writer.
*/
-int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
+int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size,
+ int preset)
{
kuid_t euid;
kgid_t egid;
@@ -264,7 +270,8 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
rcu_read_lock();
spin_lock(&new->lock);
- err = idr_get_new(&ids->ipcs_idr, new, &id);
+ err = idr_get_new_above(&ids->ipcs_idr, new,
+ ipcid_to_idx(new->id), &id);
if (err) {
spin_unlock(&new->lock);
rcu_read_unlock();
@@ -277,6 +284,11 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
new->cuid = new->uid = euid;
new->gid = new->cgid = egid;
+ if (preset && ipcid_to_idx(new->id) == id) {
+ new->seq = ipcid_to_seq(new->id);
+ return id;
+ }
+
new->seq = ids->seq++;
if(ids->seq > ids->seq_max)
ids->seq = 0;
@@ -736,7 +748,7 @@ struct kern_ipc_perm *ipc_lock_check(struct ipc_ids *ids, int id)
int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids,
struct ipc_ops *ops, struct ipc_params *params)
{
- if (params->key == IPC_PRIVATE)
+ if (params->key == IPC_PRIVATE && ((params->flg & IPC_PRESET) == 0))
return ipcget_new(ns, ids, ops, params);
else
return ipcget_public(ns, ids, ops, params);
diff --git a/ipc/util.h b/ipc/util.h
index c8fe2f7..3a9e558 100644
--- a/ipc/util.h
+++ b/ipc/util.h
@@ -92,9 +92,10 @@ void __init ipc_init_proc_interface(const char *path, const char *header,
#define IPC_SHM_IDS 2
#define ipcid_to_idx(id) ((id) % SEQ_MULTIPLIER)
+#define ipcid_to_seq(id) ((id) / SEQ_MULTIPLIER)
/* must be called with ids->rw_mutex acquired for writing */
-int ipc_addid(struct ipc_ids *, struct kern_ipc_perm *, int);
+int ipc_addid(struct ipc_ids *, struct kern_ipc_perm *, int, int);
/* must be called with ids->rw_mutex acquired for reading */
int ipc_get_maxid(struct ipc_ids *);
^ permalink raw reply related
* [PATCH v6 03/10] ipc: segment key change helper introduced
From: Stanislav Kinsbursky @ 2012-10-15 15:59 UTC (permalink / raw)
To: akpm
Cc: catalin.marinas, will.deacon, dhowells, manfred, hughd, jmorris,
mtk.manpages, kosaki.motohiro, paulmck, sds, devel, a.p.zijlstra,
cmetcalf, linux-driver, ron.mercer, viro, eparis, tglx,
jitendra.kalsaria, netdev, linux-kernel, linux-security-module,
ebiederm, casey
In-Reply-To: <20121015155800.28348.23561.stgit@localhost.localdomain>
This patch introduces existent segment key changing infrastructure.
New function ipc_update_key() can be used change segment key, cuid, cgid
values. It checks for that new key is not used (except IPC_PRIVATE) prior to
set it on existent.
To make this possible, added copying of this fields from user-space in
__get_compat_ipc_perm() and __get_compat_ipc64_perm() functions. Also segment
search by key and lock were splitted into different functions, because
ipc_update_key() doesn't need to lock the segment during check that new key is
not used.
Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
---
ipc/compat.c | 6 ++++++
ipc/util.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++---
ipc/util.h | 2 ++
3 files changed, 56 insertions(+), 3 deletions(-)
diff --git a/ipc/compat.c b/ipc/compat.c
index ad9518e..af30d13 100644
--- a/ipc/compat.c
+++ b/ipc/compat.c
@@ -144,6 +144,9 @@ static inline int __get_compat_ipc64_perm(struct ipc64_perm *p64,
err = __get_user(p64->uid, &up64->uid);
err |= __get_user(p64->gid, &up64->gid);
err |= __get_user(p64->mode, &up64->mode);
+ err |= __get_user(p64->cuid, &up64->cuid);
+ err |= __get_user(p64->cgid, &up64->cgid);
+ err |= __get_user(p64->key, &up64->key);
return err;
}
@@ -155,6 +158,9 @@ static inline int __get_compat_ipc_perm(struct ipc64_perm *p,
err = __get_user(p->uid, &up->uid);
err |= __get_user(p->gid, &up->gid);
err |= __get_user(p->mode, &up->mode);
+ err |= __get_user(p->cuid, &up->cuid);
+ err |= __get_user(p->cgid, &up->cgid);
+ err |= __get_user(p->key, &up->key);
return err;
}
diff --git a/ipc/util.c b/ipc/util.c
index 503946e..faae296 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -173,7 +173,7 @@ void __init ipc_init_proc_interface(const char *path, const char *header,
* @key: The key to find
*
* Requires ipc_ids.rw_mutex locked.
- * Returns the LOCKED pointer to the ipc structure if found or NULL
+ * Returns the UNLOCKED pointer to the ipc structure if found or NULL
* if not.
* If key is found ipc points to the owning ipc structure
*/
@@ -195,7 +195,6 @@ static struct kern_ipc_perm *ipc_findkey(struct ipc_ids *ids, key_t key)
continue;
}
- ipc_lock_by_ptr(ipc);
return ipc;
}
@@ -203,6 +202,27 @@ static struct kern_ipc_perm *ipc_findkey(struct ipc_ids *ids, key_t key)
}
/**
+ * ipc_findkey_locked - find and lock a key in an ipc identifier set
+ * @ids: Identifier set
+ * @key: The key to find
+ *
+ * Requires ipc_ids.rw_mutex locked.
+ * Returns the LOCKED pointer to the ipc structure if found or NULL
+ * if not.
+ * If key is found ipc points to the owning ipc structure
+ */
+
+static struct kern_ipc_perm *ipc_findkey_locked(struct ipc_ids *ids, key_t key)
+{
+ struct kern_ipc_perm *ipc;
+
+ ipc = ipc_findkey(ids, key);
+ if (ipc)
+ ipc_lock_by_ptr(ipc);
+ return ipc;
+}
+
+/**
* ipc_get_maxid - get the last assigned id
* @ids: IPC identifier set
*
@@ -388,7 +408,7 @@ retry:
* a new entry + read locks are not "upgradable"
*/
down_write(&ids->rw_mutex);
- ipcp = ipc_findkey(ids, params->key);
+ ipcp = ipc_findkey_locked(ids, params->key);
if (ipcp == NULL) {
/* key not used */
if (!(flg & IPC_CREAT))
@@ -755,6 +775,31 @@ int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids,
}
/**
+ * ipc_update_key - update the key of an IPC.
+ * @in: the permission given as input.
+ * @out: the permission of the ipc to set.
+ *
+ * Common routine called by sys_shmctl(), sys_semctl(). sys_msgctl().
+ */
+int ipc_update_key(struct ipc_ids *ids, struct ipc64_perm *in,
+ struct kern_ipc_perm *out)
+{
+
+ if (in->key && out->key != in->key) {
+ /*
+ * Check for existent segment with the same key.
+ * Note: ipc_ids.rw_mutex is taken for write already.
+ */
+ if (ipc_findkey(ids, in->key))
+ return -EEXIST;
+ }
+ out->cuid = in->cuid;
+ out->cgid = in->cgid;
+ out->key = in->key;
+ return 0;
+}
+
+/**
* ipc_update_perm - update the permissions of an IPC.
* @in: the permission given as input.
* @out: the permission of the ipc to set.
diff --git a/ipc/util.h b/ipc/util.h
index 3a9e558..271bded 100644
--- a/ipc/util.h
+++ b/ipc/util.h
@@ -126,6 +126,8 @@ struct kern_ipc_perm *ipc_lock(struct ipc_ids *, int);
void kernel_to_ipc64_perm(struct kern_ipc_perm *in, struct ipc64_perm *out);
void ipc64_perm_to_ipc_perm(struct ipc64_perm *in, struct ipc_perm *out);
+int ipc_update_key(struct ipc_ids *ids, struct ipc64_perm *in,
+ struct kern_ipc_perm *out);
int ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out);
struct kern_ipc_perm *ipcctl_pre_down(struct ipc_namespace *ns,
struct ipc_ids *ids, int id, int cmd,
^ permalink raw reply related
* [PATCH v6 04/10] ipc: add new SHM_SET command for sys_shmctl() call
From: Stanislav Kinsbursky @ 2012-10-15 15:59 UTC (permalink / raw)
To: akpm
Cc: catalin.marinas, will.deacon, dhowells, manfred, hughd, jmorris,
mtk.manpages, kosaki.motohiro, paulmck, sds, devel, a.p.zijlstra,
cmetcalf, linux-driver, ron.mercer, viro, eparis, tglx,
jitendra.kalsaria, netdev, linux-kernel, linux-security-module,
ebiederm, casey
In-Reply-To: <20121015155800.28348.23561.stgit@localhost.localdomain>
New SHM_SET command will be interpreted exactly as IPC_SET, but also will
update key, cuid and cgid values. IOW, it allows to change existent key value.
The fact, that key is not used is checked before update. Otherwise -EEXIST is
returned.
Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
---
include/uapi/linux/shm.h | 1 +
ipc/compat.c | 1 +
ipc/shm.c | 13 +++++++++++--
security/selinux/hooks.c | 1 +
security/smack/smack_lsm.c | 1 +
5 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/include/uapi/linux/shm.h b/include/uapi/linux/shm.h
index ec36fa1..d7413fd 100644
--- a/include/uapi/linux/shm.h
+++ b/include/uapi/linux/shm.h
@@ -56,6 +56,7 @@ struct shmid_ds {
/* ipcs ctl commands */
#define SHM_STAT 13
#define SHM_INFO 14
+#define SHM_SET 15
/* Obsolete, used only for backwards compatibility */
struct shminfo {
diff --git a/ipc/compat.c b/ipc/compat.c
index af30d13..35c750d 100644
--- a/ipc/compat.c
+++ b/ipc/compat.c
@@ -692,6 +692,7 @@ long compat_sys_shmctl(int first, int second, void __user *uptr)
case IPC_SET:
+ case SHM_SET:
if (version == IPC_64) {
err = get_compat_shmid64_ds(&s64, uptr);
} else {
diff --git a/ipc/shm.c b/ipc/shm.c
index 80b0046..aebc50d 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -636,6 +636,9 @@ copy_shmid_from_user(struct shmid64_ds *out, void __user *buf, int version)
out->shm_perm.uid = tbuf_old.shm_perm.uid;
out->shm_perm.gid = tbuf_old.shm_perm.gid;
out->shm_perm.mode = tbuf_old.shm_perm.mode;
+ out->shm_perm.cuid = tbuf_old.shm_perm.cuid;
+ out->shm_perm.cgid = tbuf_old.shm_perm.cgid;
+ out->shm_perm.key = tbuf_old.shm_perm.key;
return 0;
}
@@ -740,12 +743,13 @@ static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd,
struct shmid_kernel *shp;
int err;
- if (cmd == IPC_SET) {
+ if (cmd == IPC_SET || cmd == SHM_SET) {
if (copy_shmid_from_user(&shmid64, buf, version))
return -EFAULT;
}
- ipcp = ipcctl_pre_down(ns, &shm_ids(ns), shmid, cmd,
+ ipcp = ipcctl_pre_down(ns, &shm_ids(ns), shmid,
+ (cmd != SHM_SET) ? cmd : IPC_SET,
&shmid64.shm_perm, 0);
if (IS_ERR(ipcp))
return PTR_ERR(ipcp);
@@ -759,6 +763,10 @@ static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd,
case IPC_RMID:
do_shm_rmid(ns, ipcp);
goto out_up;
+ case SHM_SET:
+ err = ipc_update_key(&shm_ids(ns), &shmid64.shm_perm, ipcp);
+ if (err)
+ break;
case IPC_SET:
err = ipc_update_perm(&shmid64.shm_perm, ipcp);
if (err)
@@ -938,6 +946,7 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
}
case IPC_RMID:
case IPC_SET:
+ case SHM_SET:
err = shmctl_down(ns, shmid, cmd, buf, version);
return err;
default:
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 24ab414..62b2447 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -5027,6 +5027,7 @@ static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
perms = SHM__GETATTR | SHM__ASSOCIATE;
break;
case IPC_SET:
+ case SHM_SET:
perms = SHM__SETATTR;
break;
case SHM_LOCK:
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 38be92c..c7eabc9 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -2121,6 +2121,7 @@ static int smack_shm_shmctl(struct shmid_kernel *shp, int cmd)
may = MAY_READ;
break;
case IPC_SET:
+ case SHM_SET:
case SHM_LOCK:
case SHM_UNLOCK:
case IPC_RMID:
^ permalink raw reply related
* [PATCH v6 05/10] ipc: add new MSG_SET command for sys_msgctl() call
From: Stanislav Kinsbursky @ 2012-10-15 16:00 UTC (permalink / raw)
To: akpm
Cc: catalin.marinas, will.deacon, dhowells, manfred, hughd, jmorris,
mtk.manpages, kosaki.motohiro, paulmck, sds, devel, a.p.zijlstra,
cmetcalf, linux-driver, ron.mercer, viro, eparis, tglx,
jitendra.kalsaria, netdev, linux-kernel, linux-security-module,
ebiederm, casey
In-Reply-To: <20121015155800.28348.23561.stgit@localhost.localdomain>
New MSG_SET command will be interpreted exactly as IPC_SET, but also will
update key, cuid and cgid values. IOW, it allows to change existent key value.
The fact, that key is not used is checked before update. Otherwise -EEXIST is
returned.
Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
---
include/uapi/linux/msg.h | 1 +
ipc/compat.c | 1 +
ipc/msg.c | 13 +++++++++++--
security/selinux/hooks.c | 1 +
security/smack/smack_lsm.c | 1 +
5 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/include/uapi/linux/msg.h b/include/uapi/linux/msg.h
index 78dbd2f..76999c9 100644
--- a/include/uapi/linux/msg.h
+++ b/include/uapi/linux/msg.h
@@ -6,6 +6,7 @@
/* ipcs ctl commands */
#define MSG_STAT 11
#define MSG_INFO 12
+#define MSG_SET 13
/* msgrcv options */
#define MSG_NOERROR 010000 /* no error if message is too big */
diff --git a/ipc/compat.c b/ipc/compat.c
index 35c750d..9c70f9a 100644
--- a/ipc/compat.c
+++ b/ipc/compat.c
@@ -483,6 +483,7 @@ long compat_sys_msgctl(int first, int second, void __user *uptr)
break;
case IPC_SET:
+ case MSG_SET:
if (version == IPC_64) {
err = get_compat_msqid64(&m64, uptr);
} else {
diff --git a/ipc/msg.c b/ipc/msg.c
index 2f44946..68515dc 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -392,6 +392,9 @@ copy_msqid_from_user(struct msqid64_ds *out, void __user *buf, int version)
out->msg_perm.uid = tbuf_old.msg_perm.uid;
out->msg_perm.gid = tbuf_old.msg_perm.gid;
out->msg_perm.mode = tbuf_old.msg_perm.mode;
+ out->msg_perm.cuid = tbuf_old.msg_perm.cuid;
+ out->msg_perm.cgid = tbuf_old.msg_perm.cgid;
+ out->msg_perm.key = tbuf_old.msg_perm.key;
if (tbuf_old.msg_qbytes == 0)
out->msg_qbytes = tbuf_old.msg_lqbytes;
@@ -418,12 +421,13 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd,
struct msg_queue *msq;
int err;
- if (cmd == IPC_SET) {
+ if (cmd == IPC_SET || cmd == MSG_SET) {
if (copy_msqid_from_user(&msqid64, buf, version))
return -EFAULT;
}
- ipcp = ipcctl_pre_down(ns, &msg_ids(ns), msqid, cmd,
+ ipcp = ipcctl_pre_down(ns, &msg_ids(ns), msqid,
+ (cmd != MSG_SET) ? cmd : IPC_SET,
&msqid64.msg_perm, msqid64.msg_qbytes);
if (IS_ERR(ipcp))
return PTR_ERR(ipcp);
@@ -439,6 +443,7 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd,
freeque(ns, ipcp);
goto out_up;
case IPC_SET:
+ case MSG_SET:
if (msqid64.msg_qbytes > ns->msg_ctlmnb &&
!capable(CAP_SYS_RESOURCE)) {
err = -EPERM;
@@ -451,6 +456,9 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd,
msq->q_qbytes = msqid64.msg_qbytes;
+ if (cmd == MSG_SET)
+ ipc_update_key(&msg_ids(ns), &msqid64.msg_perm, ipcp);
+
msq->q_ctime = get_seconds();
/* sleeping receivers might be excluded by
* stricter permissions.
@@ -569,6 +577,7 @@ SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, struct msqid_ds __user *, buf)
}
case IPC_SET:
case IPC_RMID:
+ case MSG_SET:
err = msgctl_down(ns, msqid, cmd, buf, version);
return err;
default:
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 62b2447..78b77ac 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4885,6 +4885,7 @@ static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
perms = MSGQ__GETATTR | MSGQ__ASSOCIATE;
break;
case IPC_SET:
+ case MSG_SET:
perms = MSGQ__SETATTR;
break;
case IPC_RMID:
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index c7eabc9..d51a8da 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -2374,6 +2374,7 @@ static int smack_msg_queue_msgctl(struct msg_queue *msq, int cmd)
may = MAY_READ;
break;
case IPC_SET:
+ case MSG_SET:
case IPC_RMID:
may = MAY_READWRITE;
break;
^ permalink raw reply related
* [PATCH v6 06/10] glge driver: rename internal SEM_SET macro to SEM_INIT
From: Stanislav Kinsbursky @ 2012-10-15 16:00 UTC (permalink / raw)
To: akpm
Cc: catalin.marinas, will.deacon, dhowells, manfred, hughd, jmorris,
mtk.manpages, kosaki.motohiro, paulmck, sds, devel, a.p.zijlstra,
cmetcalf, linux-driver, ron.mercer, viro, eparis, tglx,
jitendra.kalsaria, netdev, linux-kernel, linux-security-module,
ebiederm, casey
In-Reply-To: <20121015155800.28348.23561.stgit@localhost.localdomain>
The reason for shit patch is that SET_SET is desired to be a part of new part
of API of IPC sys_semctl() system call.
The name itself for IPC is quite natural, because all linux-specific commands
names for IPC system calls are originally created by replacing "IPC_" part by
"SEM_"("MSG_", "SHM_") part.
So, I'm hoping, that this change doesn't really matters for "QLogic qlge NIC
HBA Driver" developers, since it's just an internal define.
---
drivers/net/ethernet/qlogic/qlge/qlge.h | 4 ++--
drivers/net/ethernet/qlogic/qlge/qlge_main.c | 16 ++++++++--------
2 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/qlogic/qlge/qlge.h b/drivers/net/ethernet/qlogic/qlge/qlge.h
index a131d7b..6f46ea5 100644
--- a/drivers/net/ethernet/qlogic/qlge/qlge.h
+++ b/drivers/net/ethernet/qlogic/qlge/qlge.h
@@ -347,10 +347,10 @@ enum {
enum {
/*
* Example:
- * reg = SEM_XGMAC0_MASK | (SEM_SET << SEM_XGMAC0_SHIFT)
+ * reg = SEM_XGMAC0_MASK | (SEM_INIT << SEM_XGMAC0_SHIFT)
*/
SEM_CLEAR = 0,
- SEM_SET = 1,
+ SEM_INIT = 1,
SEM_FORCE = 3,
SEM_XGMAC0_SHIFT = 0,
SEM_XGMAC1_SHIFT = 2,
diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
index b262d61..cfb0f62 100644
--- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c
+++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
@@ -109,28 +109,28 @@ static int ql_sem_trylock(struct ql_adapter *qdev, u32 sem_mask)
switch (sem_mask) {
case SEM_XGMAC0_MASK:
- sem_bits = SEM_SET << SEM_XGMAC0_SHIFT;
+ sem_bits = SEM_INIT << SEM_XGMAC0_SHIFT;
break;
case SEM_XGMAC1_MASK:
- sem_bits = SEM_SET << SEM_XGMAC1_SHIFT;
+ sem_bits = SEM_INIT << SEM_XGMAC1_SHIFT;
break;
case SEM_ICB_MASK:
- sem_bits = SEM_SET << SEM_ICB_SHIFT;
+ sem_bits = SEM_INIT << SEM_ICB_SHIFT;
break;
case SEM_MAC_ADDR_MASK:
- sem_bits = SEM_SET << SEM_MAC_ADDR_SHIFT;
+ sem_bits = SEM_INIT << SEM_MAC_ADDR_SHIFT;
break;
case SEM_FLASH_MASK:
- sem_bits = SEM_SET << SEM_FLASH_SHIFT;
+ sem_bits = SEM_INIT << SEM_FLASH_SHIFT;
break;
case SEM_PROBE_MASK:
- sem_bits = SEM_SET << SEM_PROBE_SHIFT;
+ sem_bits = SEM_INIT << SEM_PROBE_SHIFT;
break;
case SEM_RT_IDX_MASK:
- sem_bits = SEM_SET << SEM_RT_IDX_SHIFT;
+ sem_bits = SEM_INIT << SEM_RT_IDX_SHIFT;
break;
case SEM_PROC_REG_MASK:
- sem_bits = SEM_SET << SEM_PROC_REG_SHIFT;
+ sem_bits = SEM_INIT << SEM_PROC_REG_SHIFT;
break;
default:
netif_alert(qdev, probe, qdev->ndev, "bad Semaphore mask!.\n");
^ permalink raw reply related
* [PATCH v6 07/10] ipc: add new SEM_SET command for sys_semctl() call
From: Stanislav Kinsbursky @ 2012-10-15 16:00 UTC (permalink / raw)
To: akpm
Cc: catalin.marinas, will.deacon, dhowells, manfred, hughd, jmorris,
mtk.manpages, kosaki.motohiro, paulmck, sds, devel, a.p.zijlstra,
cmetcalf, linux-driver, ron.mercer, viro, eparis, tglx,
jitendra.kalsaria, netdev, linux-kernel, linux-security-module,
ebiederm, casey
In-Reply-To: <20121015155800.28348.23561.stgit@localhost.localdomain>
New SEM_SET command will be interpreted exactly as IPC_SET, but also will
update key, cuid and cgid values. IOW, it allows to change existent key value.
The fact, that key is not used is checked before update. Otherwise -EEXIST is
returned.
Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
---
include/uapi/linux/sem.h | 1 +
ipc/compat.c | 1 +
ipc/sem.c | 10 ++++++++--
security/selinux/hooks.c | 1 +
security/smack/smack_lsm.c | 1 +
5 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/include/uapi/linux/sem.h b/include/uapi/linux/sem.h
index 541fce0..b6ae374 100644
--- a/include/uapi/linux/sem.h
+++ b/include/uapi/linux/sem.h
@@ -18,6 +18,7 @@
/* ipcs ctl cmds */
#define SEM_STAT 18
#define SEM_INFO 19
+#define SEM_SET 20
/* Obsolete, used only for backwards compatibility and libc5 compiles */
struct semid_ds {
diff --git a/ipc/compat.c b/ipc/compat.c
index 9c70f9a..84d8efd 100644
--- a/ipc/compat.c
+++ b/ipc/compat.c
@@ -290,6 +290,7 @@ static long do_compat_semctl(int first, int second, int third, u32 pad)
break;
case IPC_SET:
+ case SEM_SET:
if (version == IPC_64) {
err = get_compat_semid64_ds(&s64, compat_ptr(pad));
} else {
diff --git a/ipc/sem.c b/ipc/sem.c
index 10e9085..3eac885 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -1085,12 +1085,13 @@ static int semctl_down(struct ipc_namespace *ns, int semid,
struct semid64_ds semid64;
struct kern_ipc_perm *ipcp;
- if(cmd == IPC_SET) {
+ if (cmd == IPC_SET || cmd == SEM_SET) {
if (copy_semid_from_user(&semid64, arg.buf, version))
return -EFAULT;
}
- ipcp = ipcctl_pre_down(ns, &sem_ids(ns), semid, cmd,
+ ipcp = ipcctl_pre_down(ns, &sem_ids(ns), semid,
+ (cmd != SEM_SET) ? cmd : IPC_SET,
&semid64.sem_perm, 0);
if (IS_ERR(ipcp))
return PTR_ERR(ipcp);
@@ -1105,6 +1106,10 @@ static int semctl_down(struct ipc_namespace *ns, int semid,
case IPC_RMID:
freeary(ns, ipcp);
goto out_up;
+ case SEM_SET:
+ err = ipc_update_key(&sem_ids(ns), &semid64.sem_perm, ipcp);
+ if (err)
+ break;
case IPC_SET:
err = ipc_update_perm(&semid64.sem_perm, ipcp);
if (err)
@@ -1152,6 +1157,7 @@ SYSCALL_DEFINE(semctl)(int semid, int semnum, int cmd, union semun arg)
return err;
case IPC_RMID:
case IPC_SET:
+ case SEM_SET:
err = semctl_down(ns, semid, cmd, version, arg);
return err;
default:
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 78b77ac..02b037d 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -5133,6 +5133,7 @@ static int selinux_sem_semctl(struct sem_array *sma, int cmd)
perms = SEM__DESTROY;
break;
case IPC_SET:
+ case SEM_SET:
perms = SEM__SETATTR;
break;
case IPC_STAT:
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index d51a8da..b4135ed 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -2253,6 +2253,7 @@ static int smack_sem_semctl(struct sem_array *sma, int cmd)
case SETALL:
case IPC_RMID:
case IPC_SET:
+ case SEM_SET:
may = MAY_READWRITE;
break;
case IPC_INFO:
^ permalink raw reply related
* [PATCH v6 08/10] IPC: message queue receive cleanup
From: Stanislav Kinsbursky @ 2012-10-15 16:00 UTC (permalink / raw)
To: akpm
Cc: catalin.marinas, will.deacon, dhowells, manfred, hughd, jmorris,
mtk.manpages, kosaki.motohiro, paulmck, sds, devel, a.p.zijlstra,
cmetcalf, linux-driver, ron.mercer, viro, eparis, tglx,
jitendra.kalsaria, netdev, linux-kernel, linux-security-module,
ebiederm, casey
In-Reply-To: <20121015155800.28348.23561.stgit@localhost.localdomain>
This patch moves all message related manipulation into one function msg_fill().
Actually, two functions because of the compat one.
Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
---
include/linux/msg.h | 5 +++--
ipc/compat.c | 36 +++++++++++++++++++-----------------
ipc/msg.c | 44 +++++++++++++++++++++++---------------------
3 files changed, 45 insertions(+), 40 deletions(-)
diff --git a/include/linux/msg.h b/include/linux/msg.h
index 7a4b9e9..f38edba 100644
--- a/include/linux/msg.h
+++ b/include/linux/msg.h
@@ -34,7 +34,8 @@ struct msg_queue {
/* Helper routines for sys_msgsnd and sys_msgrcv */
extern long do_msgsnd(int msqid, long mtype, void __user *mtext,
size_t msgsz, int msgflg);
-extern long do_msgrcv(int msqid, long *pmtype, void __user *mtext,
- size_t msgsz, long msgtyp, int msgflg);
+extern long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
+ int msgflg,
+ long (*msg_fill)(void __user *, struct msg_msg *, size_t ));
#endif /* _LINUX_MSG_H */
diff --git a/ipc/compat.c b/ipc/compat.c
index 84d8efd..b879d50 100644
--- a/ipc/compat.c
+++ b/ipc/compat.c
@@ -341,13 +341,23 @@ long compat_sys_msgsnd(int first, int second, int third, void __user *uptr)
return do_msgsnd(first, type, up->mtext, second, third);
}
+long compat_do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz)
+{
+ struct compat_msgbuf __user *msgp = dest;
+ size_t msgsz;
+
+ if (put_user(msg->m_type, &msgp->mtype))
+ return -EFAULT;
+
+ msgsz = (bufsz > msg->m_ts) ? msg->m_ts : bufsz;
+ if (store_msg(msgp->mtext, msg, msgsz))
+ return -EFAULT;
+ return msgsz;
+}
+
long compat_sys_msgrcv(int first, int second, int msgtyp, int third,
int version, void __user *uptr)
{
- struct compat_msgbuf __user *up;
- long type;
- int err;
-
if (first < 0)
return -EINVAL;
if (second < 0)
@@ -355,23 +365,14 @@ long compat_sys_msgrcv(int first, int second, int msgtyp, int third,
if (!version) {
struct compat_ipc_kludge ipck;
- err = -EINVAL;
if (!uptr)
- goto out;
- err = -EFAULT;
+ return -EINVAL;
if (copy_from_user (&ipck, uptr, sizeof(ipck)))
- goto out;
+ return -EFAULT;
uptr = compat_ptr(ipck.msgp);
msgtyp = ipck.msgtyp;
}
- up = uptr;
- err = do_msgrcv(first, &type, up->mtext, second, msgtyp, third);
- if (err < 0)
- goto out;
- if (put_user(type, &up->mtype))
- err = -EFAULT;
-out:
- return err;
+ return do_msgrcv(first, uptr, second, msgtyp, third, compat_do_msg_fill);
}
#else
long compat_sys_semctl(int semid, int semnum, int cmd, int arg)
@@ -394,7 +395,8 @@ long compat_sys_msgrcv(int msqid, struct compat_msgbuf __user *msgp,
{
long err, mtype;
- err = do_msgrcv(msqid, &mtype, msgp->mtext, (ssize_t)msgsz, msgtyp, msgflg);
+ err = do_msgrcv(msqid, &mtype, msgp->mtext, (ssize_t)msgsz, msgtyp,
+ msgflg, compat_do_msg_fill);
if (err < 0)
goto out;
diff --git a/ipc/msg.c b/ipc/msg.c
index 68515dc..9808da8 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -766,15 +766,30 @@ static inline int convert_mode(long *msgtyp, int msgflg)
return SEARCH_EQUAL;
}
-long do_msgrcv(int msqid, long *pmtype, void __user *mtext,
- size_t msgsz, long msgtyp, int msgflg)
+static long do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz)
+{
+ struct msgbuf __user *msgp = dest;
+ size_t msgsz;
+
+ if (put_user(msg->m_type, &msgp->mtype))
+ return -EFAULT;
+
+ msgsz = (bufsz > msg->m_ts) ? msg->m_ts : bufsz;
+ if (store_msg(msgp->mtext, msg, msgsz))
+ return -EFAULT;
+ return msgsz;
+}
+
+long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
+ int msgflg,
+ long (*msg_handler)(void __user *, struct msg_msg *, size_t ))
{
struct msg_queue *msq;
struct msg_msg *msg;
int mode;
struct ipc_namespace *ns;
- if (msqid < 0 || (long) msgsz < 0)
+ if (msqid < 0 || (long) bufsz < 0)
return -EINVAL;
mode = convert_mode(&msgtyp, msgflg);
ns = current->nsproxy->ipc_ns;
@@ -815,7 +830,7 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext,
* Found a suitable message.
* Unlink it from the queue.
*/
- if ((msgsz < msg->m_ts) && !(msgflg & MSG_NOERROR)) {
+ if ((bufsz < msg->m_ts) && !(msgflg & MSG_NOERROR)) {
msg = ERR_PTR(-E2BIG);
goto out_unlock;
}
@@ -842,7 +857,7 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext,
if (msgflg & MSG_NOERROR)
msr_d.r_maxsize = INT_MAX;
else
- msr_d.r_maxsize = msgsz;
+ msr_d.r_maxsize = bufsz;
msr_d.r_msg = ERR_PTR(-EAGAIN);
current->state = TASK_INTERRUPTIBLE;
msg_unlock(msq);
@@ -905,29 +920,16 @@ out_unlock:
if (IS_ERR(msg))
return PTR_ERR(msg);
- msgsz = (msgsz > msg->m_ts) ? msg->m_ts : msgsz;
- *pmtype = msg->m_type;
- if (store_msg(mtext, msg, msgsz))
- msgsz = -EFAULT;
-
+ bufsz = msg_handler(buf, msg, bufsz);
free_msg(msg);
- return msgsz;
+ return bufsz;
}
SYSCALL_DEFINE5(msgrcv, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz,
long, msgtyp, int, msgflg)
{
- long err, mtype;
-
- err = do_msgrcv(msqid, &mtype, msgp->mtext, msgsz, msgtyp, msgflg);
- if (err < 0)
- goto out;
-
- if (put_user(mtype, &msgp->mtype))
- err = -EFAULT;
-out:
- return err;
+ return do_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg, do_msg_fill);
}
#ifdef CONFIG_PROC_FS
^ permalink raw reply related
* [PATCH v6 09/10] IPC: message queue copy feature introduced
From: Stanislav Kinsbursky @ 2012-10-15 16:00 UTC (permalink / raw)
To: akpm
Cc: catalin.marinas, will.deacon, dhowells, manfred, hughd, jmorris,
mtk.manpages, kosaki.motohiro, paulmck, sds, devel, a.p.zijlstra,
cmetcalf, linux-driver, ron.mercer, viro, eparis, tglx,
jitendra.kalsaria, netdev, linux-kernel, linux-security-module,
ebiederm, casey
In-Reply-To: <20121015155800.28348.23561.stgit@localhost.localdomain>
This patch is required for checkpoint/restore in userspace.
IOW, c/r requires some way to get all pending IPC messages without deleting
them from the queue (checkpoint can fail and in this case tasks will be resumed,
so queue have to be valid).
To achive this, new operation flag MSG_COPY for sys_msgrcv() system call was
introduced. If this flag was specified, then mtype is interpreted as number of
the message to copy.
If MSG_COPY is set, then kernel will allocate dummy message with passed size,
and then use new copy_msg() helper function to copy desired message (instead of
unlinking it from the queue).
Notes:
1) Return -ENOSYS if MSG_COPY is specified, but CONFIG_CHECKPOINT_RESTORE is
not set.
Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
---
include/uapi/linux/msg.h | 1 +
ipc/msg.c | 50 ++++++++++++++++++++++++++++++++++++++++++++--
ipc/msgutil.c | 38 +++++++++++++++++++++++++++++++++++
ipc/util.h | 1 +
4 files changed, 88 insertions(+), 2 deletions(-)
diff --git a/include/uapi/linux/msg.h b/include/uapi/linux/msg.h
index 76999c9..c1af84a 100644
--- a/include/uapi/linux/msg.h
+++ b/include/uapi/linux/msg.h
@@ -11,6 +11,7 @@
/* msgrcv options */
#define MSG_NOERROR 010000 /* no error if message is too big */
#define MSG_EXCEPT 020000 /* recv any msg except of specified type.*/
+#define MSG_COPY 040000 /* copy (not remove) all queue messages */
/* Obsolete, used only for backwards compatibility and libc5 compiles */
struct msqid_ds {
diff --git a/ipc/msg.c b/ipc/msg.c
index 9808da8..6f52c6b 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -788,19 +788,48 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
struct msg_msg *msg;
int mode;
struct ipc_namespace *ns;
+#ifdef CONFIG_CHECKPOINT_RESTORE
+ struct msg_msg *copy = NULL;
+ unsigned long copy_number = 0;
+#endif
if (msqid < 0 || (long) bufsz < 0)
return -EINVAL;
+ if (msgflg & MSG_COPY) {
+#ifdef CONFIG_CHECKPOINT_RESTORE
+
+ if (msgflg & MSG_COPY) {
+ copy_number = msgtyp;
+ msgtyp = 0;
+ }
+
+ /*
+ * Create dummy message to copy real message to.
+ */
+ copy = load_msg(buf, bufsz);
+ if (IS_ERR(copy))
+ return PTR_ERR(copy);
+ copy->m_ts = bufsz;
+#else
+ return -ENOSYS;
+#endif
+ }
mode = convert_mode(&msgtyp, msgflg);
ns = current->nsproxy->ipc_ns;
msq = msg_lock_check(ns, msqid);
- if (IS_ERR(msq))
+ if (IS_ERR(msq)) {
+#ifdef CONFIG_CHECKPOINT_RESTORE
+ if (msgflg & MSG_COPY)
+ free_msg(copy);
+#endif
return PTR_ERR(msq);
+ }
for (;;) {
struct msg_receiver msr_d;
struct list_head *tmp;
+ long msg_counter = 0;
msg = ERR_PTR(-EACCES);
if (ipcperms(ns, &msq->q_perm, S_IRUGO))
@@ -820,8 +849,16 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
if (mode == SEARCH_LESSEQUAL &&
walk_msg->m_type != 1) {
msgtyp = walk_msg->m_type - 1;
+#ifdef CONFIG_CHECKPOINT_RESTORE
+ } else if (msgflg & MSG_COPY) {
+ if (copy_number == msg_counter) {
+ msg = copy_msg(walk_msg, copy);
+ break;
+ }
+#endif
} else
break;
+ msg_counter++;
}
tmp = tmp->next;
}
@@ -834,6 +871,10 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
msg = ERR_PTR(-E2BIG);
goto out_unlock;
}
+#ifdef CONFIG_CHECKPOINT_RESTORE
+ if (msgflg & MSG_COPY)
+ goto out_unlock;
+#endif
list_del(&msg->m_list);
msq->q_qnum--;
msq->q_rtime = get_seconds();
@@ -917,8 +958,13 @@ out_unlock:
break;
}
}
- if (IS_ERR(msg))
+ if (IS_ERR(msg)) {
+#ifdef CONFIG_CHECKPOINT_RESTORE
+ if (msgflg & MSG_COPY)
+ free_msg(copy);
+#endif
return PTR_ERR(msg);
+ }
bufsz = msg_handler(buf, msg, bufsz);
free_msg(msg);
diff --git a/ipc/msgutil.c b/ipc/msgutil.c
index 26143d3..b281f5c 100644
--- a/ipc/msgutil.c
+++ b/ipc/msgutil.c
@@ -100,7 +100,45 @@ out_err:
free_msg(msg);
return ERR_PTR(err);
}
+#ifdef CONFIG_CHECKPOINT_RESTORE
+struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst)
+{
+ struct msg_msgseg *dst_pseg, *src_pseg;
+ int len = src->m_ts;
+ int alen;
+
+ BUG_ON(dst == NULL);
+ if (src->m_ts > dst->m_ts)
+ return ERR_PTR(-EINVAL);
+
+ alen = len;
+ if (alen > DATALEN_MSG)
+ alen = DATALEN_MSG;
+
+ dst->next = NULL;
+ dst->security = NULL;
+ memcpy(dst + 1, src + 1, alen);
+
+ len -= alen;
+ dst_pseg = dst->next;
+ src_pseg = src->next;
+ while (len > 0) {
+ alen = len;
+ if (alen > DATALEN_SEG)
+ alen = DATALEN_SEG;
+ memcpy(dst_pseg + 1, src_pseg + 1, alen);
+ dst_pseg = dst_pseg->next;
+ len -= alen;
+ src_pseg = src_pseg->next;
+ }
+
+ dst->m_type = src->m_type;
+ dst->m_ts = src->m_ts;
+
+ return dst;
+}
+#endif
int store_msg(void __user *dest, struct msg_msg *msg, int len)
{
int alen;
diff --git a/ipc/util.h b/ipc/util.h
index 271bded..027f507 100644
--- a/ipc/util.h
+++ b/ipc/util.h
@@ -142,6 +142,7 @@ int ipc_parse_version (int *cmd);
extern void free_msg(struct msg_msg *msg);
extern struct msg_msg *load_msg(const void __user *src, int len);
+extern struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst);
extern int store_msg(void __user *dest, struct msg_msg *msg, int len);
extern void recompute_msgmni(struct ipc_namespace *);
^ permalink raw reply related
* [PATCH v6 10/10] test: IPC message queue copy feture test
From: Stanislav Kinsbursky @ 2012-10-15 16:00 UTC (permalink / raw)
To: akpm
Cc: catalin.marinas, will.deacon, dhowells, manfred, hughd, jmorris,
mtk.manpages, kosaki.motohiro, paulmck, sds, devel, a.p.zijlstra,
cmetcalf, linux-driver, ron.mercer, viro, eparis, tglx,
jitendra.kalsaria, netdev, linux-kernel, linux-security-module,
ebiederm, casey
In-Reply-To: <20121015155800.28348.23561.stgit@localhost.localdomain>
This test can be used to check wheither kernel supports IPC message queue copy
and restore features (required by CRIU project).
---
tools/testing/selftests/ipc/Makefile | 28 ++++
tools/testing/selftests/ipc/msgque.c | 251 ++++++++++++++++++++++++++++++++++
2 files changed, 279 insertions(+), 0 deletions(-)
create mode 100644 tools/testing/selftests/ipc/Makefile
create mode 100644 tools/testing/selftests/ipc/msgque.c
diff --git a/tools/testing/selftests/ipc/Makefile b/tools/testing/selftests/ipc/Makefile
new file mode 100644
index 0000000..6c547bf
--- /dev/null
+++ b/tools/testing/selftests/ipc/Makefile
@@ -0,0 +1,28 @@
+uname_M := $(shell uname -m 2>/dev/null || echo not)
+ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/)
+ifeq ($(ARCH),i386)
+ ARCH := X86
+ CFLAGS := -DCONFIG_X86_32 -D__i386__
+endif
+ifeq ($(ARCH),x86_64)
+ ARCH := X86
+ CFLAGS := -DCONFIG_X86_64 -D__x86_64__
+endif
+
+CFLAGS += -I../../../../arch/x86/include/generated/
+CFLAGS += -I../../../../include/
+CFLAGS += -I../../../../usr/include/
+CFLAGS += -I../../../../arch/x86/include/
+
+all:
+ifeq ($(ARCH),X86)
+ gcc $(CFLAGS) msgque.c -o msgque_test
+else
+ echo "Not an x86 target, can't build msgque selftest"
+endif
+
+run_tests: all
+ ./msgque_test
+
+clean:
+ rm -fr ./msgque_test
diff --git a/tools/testing/selftests/ipc/msgque.c b/tools/testing/selftests/ipc/msgque.c
new file mode 100644
index 0000000..ffcc8b7
--- /dev/null
+++ b/tools/testing/selftests/ipc/msgque.c
@@ -0,0 +1,251 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define MAX_MSG_SIZE 32
+
+struct msg1 {
+ int msize;
+ long mtype;
+ char mtext[MAX_MSG_SIZE];
+};
+
+#define TEST_STRING "Test sysv5 msg"
+#define MSG_TYPE 1
+
+#define ANOTHER_TEST_STRING "Yet another test sysv5 msg"
+#define ANOTHER_MSG_TYPE 26538
+
+#ifndef IPC_PRESET
+#define IPC_PRESET 00040000
+#endif
+
+#ifndef MSG_COPY
+#define MSG_COPY 040000
+#endif
+
+#ifndef MSG_SET
+#define MSG_SET 13
+#endif
+
+#if defined (__GLIBC__) && __GLIBC__ >= 2
+#define KEY __key
+#else
+#define KEY key
+#endif
+
+struct msgque_data {
+ int msq_id;
+ int qbytes;
+ int kern_id;
+ int qnum;
+ int mode;
+ struct msg1 *messages;
+};
+
+int restore_queue(struct msgque_data *msgque)
+{
+ struct msqid_ds ds;
+ int id, i;
+
+ id = msgget(msgque->msq_id,
+ msgque->mode | IPC_CREAT | IPC_EXCL | IPC_PRESET);
+ if (id == -1) {
+ printf("Failed to create queue\n");
+ return -errno;
+ }
+
+ if (id != msgque->msq_id) {
+ printf("Failed to preset id (%d instead of %d)\n",
+ id, msgque->msq_id);
+ return -EFAULT;
+ }
+
+ if (msgctl(id, MSG_STAT, &ds) < 0) {
+ printf("Failed to stat queue\n");
+ return -errno;
+ }
+
+ ds.msg_perm.KEY = msgque->msq_id;
+ ds.msg_qbytes = msgque->qbytes;
+ if (msgctl(id, MSG_SET, &ds) < 0) {
+ printf("Failed to update message key\n");
+ return -errno;
+ }
+
+ for (i = 0; i < msgque->qnum; i++) {
+ if (msgsnd(msgque->msq_id, &msgque->messages[i].mtype, msgque->messages[i].msize, IPC_NOWAIT) != 0) {
+ printf("msgsnd failed (%m)\n");
+ return -errno;
+ };
+ }
+ return 0;
+}
+
+int check_and_destroy_queue(struct msgque_data *msgque)
+{
+ struct msg1 message;
+ int cnt = 0, ret;
+
+ while (1) {
+ ret = msgrcv(msgque->msq_id, &message.mtype, MAX_MSG_SIZE, 0, IPC_NOWAIT);
+ if (ret < 0) {
+ if (errno == ENOMSG)
+ break;
+ printf("Failed to read IPC message: %m\n");
+ ret = -errno;
+ goto err;
+ }
+ if (ret != msgque->messages[cnt].msize) {
+ printf("Wrong message size: %d (expected %d)\n", ret, msgque->messages[cnt].msize);
+ ret = -EINVAL;
+ goto err;
+ }
+ if (message.mtype != msgque->messages[cnt].mtype) {
+ printf("Wrong message type\n");
+ ret = -EINVAL;
+ goto err;
+ }
+ if (memcmp(message.mtext, msgque->messages[cnt].mtext, ret)) {
+ printf("Wrong message content\n");
+ ret = -EINVAL;
+ goto err;
+ }
+ cnt++;
+ }
+
+ if (cnt != msgque->qnum) {
+ printf("Wrong message number\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ret = 0;
+err:
+ if (msgctl(msgque->msq_id, IPC_RMID, 0)) {
+ printf("Failed to destroy queue: %d\n", -errno);
+ return -errno;
+ }
+ return ret;
+}
+
+int dump_queue(struct msgque_data *msgque)
+{
+ struct msqid_ds ds;
+ int i, ret;
+
+ for (msgque->kern_id = 0; msgque->kern_id < 256; msgque->kern_id++) {
+ ret = msgctl(msgque->kern_id, MSG_STAT, &ds);
+ if (ret < 0) {
+ if (errno == -EINVAL)
+ continue;
+ printf("Failed to get stats for IPC queue with id %d\n", msgque->kern_id);
+ return -errno;
+ }
+
+ if (ret == msgque->msq_id)
+ break;
+ }
+
+ msgque->messages = malloc(sizeof(struct msg1) * ds.msg_qnum);
+ if (msgque->messages == NULL) {
+ printf("Failed to get stats for IPC queue\n");
+ return -ENOMEM;
+ }
+
+ msgque->qnum = ds.msg_qnum;
+ msgque->mode = ds.msg_perm.mode;
+ msgque->qbytes = ds.msg_qbytes;
+
+ for (i = 0; i < msgque->qnum; i++) {
+ ret = msgrcv(msgque->msq_id, &msgque->messages[i].mtype, MAX_MSG_SIZE, i, IPC_NOWAIT | MSG_COPY);
+ if (ret < 0) {
+ printf("Failed to copy IPC message: %m (%d)\n", errno);
+ return -errno;
+ }
+ msgque->messages[i].msize = ret;
+ }
+ return 0;
+}
+
+int fill_msgque(struct msgque_data *msgque)
+{
+ struct msg1 msgbuf;
+
+ msgbuf.mtype = MSG_TYPE;
+ memcpy(msgbuf.mtext, TEST_STRING, sizeof(TEST_STRING));
+ if (msgsnd(msgque->msq_id, &msgbuf.mtype, sizeof(TEST_STRING), IPC_NOWAIT) != 0) {
+ printf("First message send failed (%m)\n");
+ return -errno;
+ };
+
+ msgbuf.mtype = ANOTHER_MSG_TYPE;
+ memcpy(msgbuf.mtext, ANOTHER_TEST_STRING, sizeof(ANOTHER_TEST_STRING));
+ if (msgsnd(msgque->msq_id, &msgbuf.mtype, sizeof(ANOTHER_TEST_STRING), IPC_NOWAIT) != 0) {
+ printf("Second message send failed (%m)\n");
+ return -errno;
+ };
+ return 0;
+}
+
+int main (int argc, char **argv)
+{
+ key_t key;
+ int msg, pid, err;
+ struct msgque_data msgque;
+
+ key = ftok(argv[0], 822155650);
+ if (key == -1) {
+ printf("Can't make key\n");
+ return -errno;
+ }
+
+ msgque.msq_id = msgget(key, IPC_CREAT | IPC_EXCL | 0666);
+ if (msgque.msq_id == -1) {
+ printf("Can't create queue\n");
+ goto err_out;
+ }
+
+ err = fill_msgque(&msgque);
+ if (err) {
+ printf("Failed to fill queue\n");
+ goto err_destroy;
+ }
+
+ err = dump_queue(&msgque);
+ if (err) {
+ printf("Failed to dump queue\n");
+ goto err_destroy;
+ }
+
+ err = check_and_destroy_queue(&msgque);
+ if (err) {
+ printf("Failed to check and destroy queue\n");
+ goto err_out;
+ }
+
+ err = restore_queue(&msgque);
+ if (err) {
+ printf("Failed to restore queue\n");
+ goto err_destroy;
+ }
+
+ err = check_and_destroy_queue(&msgque);
+ if (err) {
+ printf("Failed to test queue\n");
+ goto err_out;
+ }
+ return 0;
+
+err_destroy:
+ if (msgctl(msgque.msq_id, IPC_RMID, 0)) {
+ printf("Failed to destroy queue: %d\n", -errno);
+ return -errno;
+ }
+err_out:
+ return err;
+}
^ permalink raw reply related
* [PATCH] r8169: Kill SafeMtu macro
From: Kirill Smelkov @ 2012-10-15 16:16 UTC (permalink / raw)
To: Francois Romieu; +Cc: netdev, Kirill Smelkov
After d58d46b5 (r8169: jumbo fixes.) max frame len is stored in
rtl_chip_infos[].jumbo_max for each chip and SafeMtu should be gone.
Signed-off-by: Kirill Smelkov <kirr@mns.spb.ru>
---
drivers/net/ethernet/realtek/r8169.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index e7ff886..7ca6618 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -78,7 +78,6 @@ static const int multicast_filter_limit = 32;
#define MAX_READ_REQUEST_SHIFT 12
#define TX_DMA_BURST 7 /* Maximum PCI burst, '7' is unlimited */
-#define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */
#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */
#define R8169_REGS_SIZE 256
--
1.8.0.rc1.231.g17358b9
^ permalink raw reply related
* Re: listen(2) backlog changes in or around Linux 3.1?
From: Venkat Venkatsubra @ 2012-10-15 17:12 UTC (permalink / raw)
To: enh; +Cc: netdev
In-Reply-To: <CAJgzZorigejCuFweNrvmkEJts3Um7exh1fYTH=4KrEcB=v=2SA@mail.gmail.com>
On 10/12/2012 6:40 PM, enh wrote:
> i used to use the following hack to unit test connect timeouts: i'd
> call listen(2) on a socket and then deliberately connect (backlog + 3)
> sockets without accept(2)ing any of the connections. (why 3? because
> Stevens told me so, and experiment backed him up. see figure 4.10 in
> his UNIX Network Programming.)
>
> with "old" kernels, 2.6.35-ish to 3.0-ish, this worked great. my next
> connect(2) to the same loopback port would hang indefinitely. i could
> even unblock the connect by calling accept(2) in another thread. this
> was awesome for testing.
>
> in 3.1 on ARM, 3.2 on x86 (Ubuntu desktop), and 3.4 on ARM, this no
> longer works. it doesn't seem to be as simple as "the constant is no
> longer 3". my tests are now flaky. sometimes they work like they used
> to, and sometimes an extra connect(2) will succeed. (or, if i'm in
> non-blocking mode, my poll(2) will return with the non-blocking socket
> that's trying to connect now ready.)
>
> i'm guessing if this changed in 3.1 and is still changed in 3.4,
> whatever's changed wasn't an accident. but i haven't been able to find
> the right search terms to RTFM. i also finally got around to grepping
> the kernel for the "+ 3", but wasn't able to find that. (so i'd be
> interested to know where the old behavior came from too.)
>
> my least worst workaround at the moment is to use one of RFC5737's
> test networks, but that requires that the device have a network
> connection, otherwise my connect(2)s fail immediately with
> ENETUNREACH, which is no use to me. also, unlike my old trick, i've
> got no way to suddenly "unblock" a slow connect(2) (this is useful for
> unit testing the code that does the poll(2) part of the usual
> connect-with-timeout implementation).
> https://android-review.googlesource.com/#/c/44563/
>
> hopefully someone here can shed some light on this? ideally someone
> will have a workaround as good as my old trick. i realize i was
> relying on undocumented behavior, and i'm happy to have to check
> /proc/version and behave appropriately, but i'd really like a way to
> keep my unit tests!
>
> thanks,
> elliott
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi Elliott,
In BSD I think the backlog used to be reset to 3/2 times that passed by
the user. So, 2 becomes 3.
Probably the 1/2 times increase was to accommodate the ones in
partial/incomplete queue.
In Linux is it possible you were getting the same behavior before the
below commit ?
Since the check used to be "backlog+1" a 2 will behave as 3 ?
commit 8488df894d05d6fa41c2bd298c335f944bb0e401
Author: Wei Dong <weid@np.css.fujitsu.com>
Date: Fri Mar 2 12:37:26 2007 -0800
[NET]: Fix bugs in "Whether sock accept queue is full" checking
when I use linux TCP socket, and find there is a bug in
function sk_acceptq_is_full().
When a new SYN comes, TCP module first checks its validation.
If valid,
send SYN,ACK to the client and add the sock to the syn hash table. Next
time if received the valid ACK for SYN,ACK from the client. server will
accept this connection and increase the sk->sk_ack_backlog -- which is
done in function tcp_check_req().We check wether acceptq is full in
function tcp_v4_syn_recv_sock().
Consider an example:
After listen(sockfd, 1) system call, sk->sk_max_ack_backlog is set to
1. As we know, sk->sk_ack_backlog is initialized to 0. Assuming
accept()
system call is not invoked now.
1. 1st connection comes. invoke sk_acceptq_is_full().
sk->sk_ack_backlog=0 sk->sk_max_ack_backlog=1, function return 0
accept this connection.
Increase the sk->sk_ack_backlog
2. 2nd connection comes. invoke sk_acceptq_is_full().
sk->sk_ack_backlog=1 sk->sk_max_ack_backlog=1, function return 0
accept this connection.
Increase the sk->sk_ack_backlog
3. 3rd connection comes. invoke sk_acceptq_is_full().
sk->sk_ack_backlog=2 sk->sk_max_ack_backlog=1, function return 1.
Refuse this connection.
I think it has bugs. after listen system call. sk->sk_max_ack_backlog=1
but now it can accept 2 connections.
Signed-off-by: Wei Dong <weid@np.css.fujitsu.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Venkat
^ permalink raw reply
* Re: listen(2) backlog changes in or around Linux 3.1?
From: enh @ 2012-10-15 17:26 UTC (permalink / raw)
To: Venkat Venkatsubra; +Cc: netdev
In-Reply-To: <507C4401.7050500@oracle.com>
On Mon, Oct 15, 2012 at 10:12 AM, Venkat Venkatsubra
<venkat.x.venkatsubra@oracle.com> wrote:
> On 10/12/2012 6:40 PM, enh wrote:
>>
>> i used to use the following hack to unit test connect timeouts: i'd
>> call listen(2) on a socket and then deliberately connect (backlog + 3)
>> sockets without accept(2)ing any of the connections. (why 3? because
>> Stevens told me so, and experiment backed him up. see figure 4.10 in
>> his UNIX Network Programming.)
>>
>> with "old" kernels, 2.6.35-ish to 3.0-ish, this worked great. my next
>> connect(2) to the same loopback port would hang indefinitely. i could
>> even unblock the connect by calling accept(2) in another thread. this
>> was awesome for testing.
>>
>> in 3.1 on ARM, 3.2 on x86 (Ubuntu desktop), and 3.4 on ARM, this no
>> longer works. it doesn't seem to be as simple as "the constant is no
>> longer 3". my tests are now flaky. sometimes they work like they used
>> to, and sometimes an extra connect(2) will succeed. (or, if i'm in
>> non-blocking mode, my poll(2) will return with the non-blocking socket
>> that's trying to connect now ready.)
>>
>> i'm guessing if this changed in 3.1 and is still changed in 3.4,
>> whatever's changed wasn't an accident. but i haven't been able to find
>> the right search terms to RTFM. i also finally got around to grepping
>> the kernel for the "+ 3", but wasn't able to find that. (so i'd be
>> interested to know where the old behavior came from too.)
>>
>> my least worst workaround at the moment is to use one of RFC5737's
>> test networks, but that requires that the device have a network
>> connection, otherwise my connect(2)s fail immediately with
>> ENETUNREACH, which is no use to me. also, unlike my old trick, i've
>> got no way to suddenly "unblock" a slow connect(2) (this is useful for
>> unit testing the code that does the poll(2) part of the usual
>> connect-with-timeout implementation).
>> https://android-review.googlesource.com/#/c/44563/
>>
>> hopefully someone here can shed some light on this? ideally someone
>> will have a workaround as good as my old trick. i realize i was
>> relying on undocumented behavior, and i'm happy to have to check
>> /proc/version and behave appropriately, but i'd really like a way to
>> keep my unit tests!
>>
>> thanks,
>> elliott
>> --
>> To unsubscribe from this list: send the line "unsubscribe netdev" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
> Hi Elliott,
>
> In BSD I think the backlog used to be reset to 3/2 times that passed by the
> user. So, 2 becomes 3.
> Probably the 1/2 times increase was to accommodate the ones in
> partial/incomplete queue.
> In Linux is it possible you were getting the same behavior before the below
> commit ?
> Since the check used to be "backlog+1" a 2 will behave as 3 ?
i don't think so, because with <= 3.0 kernels i used to have a backlog
of 1 and be able to make _4_ connections before my next connect would
hang. but this > to >= change is at least something for me to
investigate...
> commit 8488df894d05d6fa41c2bd298c335f944bb0e401
> Author: Wei Dong <weid@np.css.fujitsu.com>
> Date: Fri Mar 2 12:37:26 2007 -0800
>
> [NET]: Fix bugs in "Whether sock accept queue is full" checking
>
> when I use linux TCP socket, and find there is a bug in function
> sk_acceptq_is_full().
>
> When a new SYN comes, TCP module first checks its validation. If
> valid,
> send SYN,ACK to the client and add the sock to the syn hash table. Next
> time if received the valid ACK for SYN,ACK from the client. server will
> accept this connection and increase the sk->sk_ack_backlog -- which is
> done in function tcp_check_req().We check wether acceptq is full in
> function tcp_v4_syn_recv_sock().
>
> Consider an example:
>
> After listen(sockfd, 1) system call, sk->sk_max_ack_backlog is set to
> 1. As we know, sk->sk_ack_backlog is initialized to 0. Assuming accept()
> system call is not invoked now.
>
> 1. 1st connection comes. invoke sk_acceptq_is_full().
> sk->sk_ack_backlog=0 sk->sk_max_ack_backlog=1, function return 0 accept
> this connection.
> Increase the sk->sk_ack_backlog
> 2. 2nd connection comes. invoke sk_acceptq_is_full().
> sk->sk_ack_backlog=1 sk->sk_max_ack_backlog=1, function return 0 accept
> this connection.
> Increase the sk->sk_ack_backlog
> 3. 3rd connection comes. invoke sk_acceptq_is_full().
> sk->sk_ack_backlog=2 sk->sk_max_ack_backlog=1, function return 1.
> Refuse this connection.
>
> I think it has bugs. after listen system call. sk->sk_max_ack_backlog=1
> but now it can accept 2 connections.
>
> Signed-off-by: Wei Dong <weid@np.css.fujitsu.com>
> Signed-off-by: David S. Miller <davem@davemloft.net>
>
> Venkat
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox