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

This commit is contained in:
Joseph Henry 2015-10-13 18:33:56 -04:00
parent 8a05efa365
commit aa6ff039c4
3 changed files with 48 additions and 23 deletions

View file

@ -490,6 +490,12 @@ int NetconEthernetTap::send_return_value(int fd, int retval, int _errno = 0)
* @param error code * @param error code
* @return ERR_OK if everything is ok, -1 otherwise * @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 [ ] 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 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, 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. [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). [ ] 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 - 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. [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. [ ] 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 [ ] 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. 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. [I] EOPNOTSUPP - The referenced socket is not of type SOCK_STREAM.
[ ] EPROTO - Protocol error. [ ] 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. [ ] EACCES - The address is protected, and the user is not the superuser.
[X] EADDRINUSE - The given address is already in use. [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. [X] EINVAL - The socket is already bound to an address.
[i] ENOTSOCK - sockfd is a descriptor for a file, not a socket. [I] ENOTSOCK - sockfd is a descriptor for a file, not a socket.
[-] The following errors are specific to UNIX domain (AF_UNIX) sockets:
- 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).) [-] 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. [-] EADDRNOTAVAIL - A nonexistent interface was requested or the requested address was not local.
[-] EFAULT - addr points outside the user's accessible address space. [-] EFAULT - addr points outside the user's accessible address space.

View file

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

Binary file not shown.