diff mbox

net: Fix security_socket_sendmsg() bypass problem.

Message ID 20110803232957.5e7a5d0a@kryten
State Superseded, archived
Delegated to: David Miller
Headers show

Commit Message

Anton Blanchard Aug. 3, 2011, 1:29 p.m. UTC
Hi,

> > I much prefer to make the error handling more correct, rather than
> > making sendmmsg() have fundamentally different semantics depending
> > upon the underlying LSM.
> 
> Well, the way how sendmmsg() returns error code is tricky. But
> recvmmsg() has been doing in this way for a while. So, for symmetry
> reason, maybe sendmmsg() should do as with recvmmsg() since it is too
> late to change recvmmsg()'s way.
> 
> So, programmers should be warned (in the man pages) that they should
> always call getsockopt(SO_ERROR) (in order to clear the error code)
> if sendmmsg() or recvmmsg() returned less than requested.

As you suggest, I wanted to mirror how recvmmsg returns errors. But I
now agree with Dave, we should not return an error if we managed to send
any datagrams.

Perhaps we need to modify recvmmsg to do the same?

> By the way, don't we want integer overflow check and/or
> cond_resched() here? I don't know whether there is an arch where
> userspace can allocate (1 << BITS_PER_INT) * sizeof(struct msghdr)
> bytes using malloc() and kernel can allocate huge memory for the
> socket buffer.
> 
> #include <stdio.h>
> int main(int argc, char *argv[])
> {
>         int datagrams = 0;
>         unsigned int vlen = 4294967290U;
>         while (datagrams < vlen)
>                 datagrams++;
>         printf("%u\n", datagrams);
>         return 0;
> }
> 
> I think this program (on x86_32) will print an IS_ERR() value upon
> success.

Good catch. I wonder if we can do something similar to read/write where
we just truncate the length. What value should we use? One option is to
reuse UIO_MAXIOV (1024).

The following patch is compiled tested only so far.

Anton
--

[PATCH] net: Cap number of elements for recvmmsg and sendmmsg 

To limit the amount of time we can spend in recvmmsg and sendmmsg,
cap the number of elements to UIO_MAXIOV (currently 1024). 
       
Signed-off-by: Anton Blanchard <anton@samba.org>
Cc: <stable@kernel.org>
---

--
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

Comments

Eduard Sinelnikov Aug. 3, 2011, 1:37 p.m. UTC | #1
Hi,

The scenario:
The scenario is:
* Create a bond with 3 interfaces (connect them to switch).
* Change bond's mode to active/backup.
* Physicly remove two cables form interfaces ( not the active interface ).
* Put the cables back
* Change the mode to round robin.
* Try to ping some other computer.

Now only one interface is pinging to remote computer.
Without removing the cables all three interface will ping to remote
computer periodicly.



The problem:
In the kernel 2.6.39.3 ( /drivers/net/bond/bond_main.c).
In the function  ‘bond_xmit_roundrobin’
The code check if the bond is active via
‘bond_is_active_slave(slave)’ Function call.
Which actually checks if the slave is backup or active
What is the meaning of slave being  backup in round robin mode?
Correct me if I wrong but in round robin every slave should send a
packet, regardless of being active or backup.

Thank you,
           Eduard
--
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
Tetsuo Handa Aug. 3, 2011, 9:50 p.m. UTC | #2
Anton Blanchard wrote:
> [PATCH] net: Cap number of elements for recvmmsg and sendmmsg
> 
> To limit the amount of time we can spend in recvmmsg and sendmmsg,
> cap the number of elements to UIO_MAXIOV (currently 1024).

Looks reasonable value. But it will return less than requested without setting
error code. Programmers would needlessly call getsockopt(SO_ERROR) and get 0.
Maybe -EINVAL or something is better than returning less than requested?
--
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
Anton Blanchard Aug. 4, 2011, 12:56 p.m. UTC | #3
Hi,

> > [PATCH] net: Cap number of elements for recvmmsg and sendmmsg
> > 
> > To limit the amount of time we can spend in recvmmsg and sendmmsg,
> > cap the number of elements to UIO_MAXIOV (currently 1024).
> 
> Looks reasonable value. But it will return less than requested
> without setting error code. Programmers would needlessly call
> getsockopt(SO_ERROR) and get 0. Maybe -EINVAL or something is better
> than returning less than requested?

Having to call getsockopt(SO_ERROR) at all is confusing. We should
change sendmmsg to only return an error if no messages are sent. If we
do this, then the application will have already have to handle the case
where we send less messages than requested.

Returning EINVAL adds complexity to the system call that I think we
should avoid. Will send out the patches for review after some sleep.

Anton
--
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
diff mbox

Patch

diff --git a/net/socket.c b/net/socket.c
index b1cbbcd..ad345b1 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1999,6 +1999,9 @@  int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
 	struct compat_mmsghdr __user *compat_entry;
 	struct msghdr msg_sys;
 
+	if (vlen > UIO_MAXIOV)
+		vlen = UIO_MAXIOV;
+
 	datagrams = 0;
 
 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
@@ -2199,6 +2202,9 @@  int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
 	struct msghdr msg_sys;
 	struct timespec end_time;
 
+	if (vlen > UIO_MAXIOV)
+		vlen = UIO_MAXIOV;
+
 	if (timeout &&
 	    poll_select_set_timeout(&end_time, timeout->tv_sec,
 				    timeout->tv_nsec))