Browse Source

Improved bind() logic, added more error handling to accept()

Joseph Henry 9 years ago
parent
commit
aa6ff039c4
3 changed files with 48 additions and 23 deletions
  1. 13 5
      netcon/NetconEthernetTap.cpp
  2. 35 18
      netcon/intercept.c
  3. BIN
      netcon/libintercept.so.1.0

+ 13 - 5
netcon/NetconEthernetTap.cpp

@@ -490,6 +490,12 @@ int NetconEthernetTap::send_return_value(int fd, int retval, int _errno = 0)
  * @param error code
  * @return ERR_OK if everything is ok, -1 otherwise
 
+	 i := should be implemented in intercept lib
+	 I := is implemented in intercept lib
+	 X := is implemented in service
+	 ? := required treatment Unknown
+	 - := Not needed
+
 	[ ] EAGAIN or EWOULDBLOCK - The socket is marked nonblocking and no connections are present
 													to be accepted. POSIX.1-2001 allows either error to be returned for
 													this case, and does not require these constants to have the same value,
@@ -499,12 +505,12 @@ int NetconEthernetTap::send_return_value(int fd, int retval, int _errno = 0)
 	[i] EFAULT - The addr argument is not in a writable part of the user address space.
 	[ ] EINTR - The system call was interrupted by a signal that was caught before a valid connection arrived; see signal(7).
 	[ ] EINVAL - Socket is not listening for connections, or addrlen is invalid (e.g., is negative).
-	[ ] EINVAL - (accept4()) invalid value in flags.
+	[I] EINVAL - (accept4()) invalid value in flags.
 	[I] EMFILE - The per-process limit of open file descriptors has been reached.
 	[ ] ENFILE - The system limit on the total number of open files has been reached.
 	[ ] ENOBUFS, ENOMEM - Not enough free memory. This often means that the memory allocation is
 												limited by the socket buffer limits, not by the system memory.
-	[i] ENOTSOCK - The descriptor references a file, not a socket.
+	[I] ENOTSOCK - The descriptor references a file, not a socket.
 	[I] EOPNOTSUPP - The referenced socket is not of type SOCK_STREAM.
 	[ ] EPROTO - Protocol error.
 
@@ -802,10 +808,12 @@ void NetconEthernetTap::handle_retval(PhySocket *sock, void **uptr, unsigned cha
 
 	[ ]	EACCES - The address is protected, and the user is not the superuser.
 	[X]	EADDRINUSE - The given address is already in use.
-	[X]	EBADF - sockfd is not a valid descriptor.
+	[I]	EBADF - sockfd is not a valid descriptor.
 	[X]	EINVAL - The socket is already bound to an address.
-	[i]	ENOTSOCK - sockfd is a descriptor for a file, not a socket.
-	[-]	The following errors are specific to UNIX domain (AF_UNIX) sockets:
+	[I]	ENOTSOCK - sockfd is a descriptor for a file, not a socket.
+
+	  - The following errors are specific to UNIX domain (AF_UNIX) sockets:
+
 	[-]	EACCES - Search permission is denied on a component of the path prefix. (See also path_resolution(7).)
 	[-]	EADDRNOTAVAIL - A nonexistent interface was requested or the requested address was not local.
 	[-]	EFAULT - addr points outside the user's accessible address space.

+ 35 - 18
netcon/intercept.c

@@ -688,6 +688,21 @@ int poll(POLL_SIG)
    bind() intercept function */
 int bind(BIND_SIG)
 {
+#ifdef CHECKS
+  /* Check that this is a valid fd */
+  if(fcntl(sockfd, F_GETFD) < 0) {
+    return -1;
+    errno = EBADF;
+  }
+  /* Check that it is a socket */
+  int sock_type = -1;
+  socklen_t sock_type_len = sizeof(sock_type);
+  if(getsockopt(sockfd, SOL_SOCKET, SO_TYPE, (void *) &sock_type, &sock_type_len) < 0) {
+    errno = ENOTSOCK;
+    return -1;
+  }
+#endif
+
   int err;
 #ifdef DUMMY
     dwr("bind(%d)\n", sockfd);
@@ -697,28 +712,23 @@ int bind(BIND_SIG)
   if(sockfd == STDIN_FILENO || sockfd == STDOUT_FILENO || sockfd == STDERR_FILENO)
     return(realbind(sockfd, addr, addrlen));
 
-  int sock_type = -1;
-  socklen_t sock_type_len = sizeof(sock_type);
+  /* If local, just use normal syscall */
   struct sockaddr_in *connaddr;
   connaddr = (struct sockaddr_in *) addr;
 
-  getsockopt(sockfd, SOL_SOCKET, SO_TYPE,
-       (void *) &sock_type, &sock_type_len);
-
   if (addr != NULL && (connaddr->sin_family == AF_LOCAL
     || connaddr->sin_family == PF_NETLINK
     || connaddr->sin_family == AF_NETLINK
-    || connaddr->sin_family == AF_UNIX)) {
-   return(realbind(sockfd, addr, addrlen));
-  }
-
-  char cmd[BUF_SZ];
-  if(realbind == NULL) {
-    dwr("Unresolved symbol: bind()\n");
-    return -1;
+    || connaddr->sin_family == AF_UNIX))
+  {
+      if(realbind == NULL) {
+        dwr("Unresolved symbol: bind(). Library is exiting.\n");
+        exit(-1);
+      }
+      return(realbind(sockfd, addr, addrlen));
   }
-
   /* Assemble and route command */
+  char cmd[BUF_SZ];
   struct bind_st rpc_st;
   rpc_st.sockfd = sockfd;
   rpc_st.__tid = syscall(SYS_gettid);
@@ -768,16 +778,22 @@ int accept(ACCEPT_SIG)
 #ifdef CHECKS
   /* Check that this is a valid fd */
   if(fcntl(sockfd, F_GETFD) < 0) {
+    dwr("EBADF\n");
     return -1;
     errno = EBADF;
   }
-  int sock_type = -1;
+  /* Check that it is a socket */
+  int sock_type;
   socklen_t sock_type_len = sizeof(sock_type);
-  getsockopt(sockfd, SOL_SOCKET, SO_TYPE,
-       (void *) &sock_type, &sock_type_len);
+  if(getsockopt(sockfd, SOL_SOCKET, SO_TYPE, (void *) &sock_type, &sock_type_len) < 0) {
+    errno = ENOTSOCK;
+    dwr("ENOTSOCK\n");
+    return -1;
+  }
   /* Check that this socket supports accept() */
-  if(!(sock_type & (SOCK_STREAM | SOCK_SEQPACKET))) {
+  if(!(sock_type && (SOCK_STREAM | SOCK_SEQPACKET))) {
     errno = EOPNOTSUPP;
+    dwr("EOPNOTSUPP\n");
     return -1;
   }
   /* Check that we haven't hit the soft-limit file descriptors allowed */
@@ -785,6 +801,7 @@ int accept(ACCEPT_SIG)
   getrlimit(RLIMIT_NOFILE, &rl);
   if(sockfd >= rl.rlim_cur){
     errno = EMFILE;
+    dwr("EMFILE\n");
     return -1;
   }
 #endif

BIN
netcon/libintercept.so.1.0