Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Work in progress: Implement syscall connect #14

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,7 @@ example-programs-build/write-EBADF: example-programs/write-EBADF.c
example-programs-build/access-itself: example-programs/access-itself.c
mkdir -p example-programs-build
gcc -static -std=c99 -Wall -Werror example-programs/access-itself.c -o example-programs-build/access-itself

example-programs-build/connect: example-programs/connect.c
mkdir -p example-programs-build
gcc -static -std=c99 -Wall -Werror example-programs/connect.c -o example-programs-build/connect
106 changes: 106 additions & 0 deletions example-programs/connect.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <linux/netlink.h>
#include <linux/un.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>

void die_usage(void)
{
fprintf(stderr, "Usage: connect [FLAG]\n");
exit(1);
}

void connectInet6()
{
int sockfd = socket(AF_INET6, SOCK_STREAM, 0);
stefanjaax marked this conversation as resolved.
Show resolved Hide resolved
if(sockfd < 0){
printf("\n Error : Could not create Inet6 socket \n");
exit(1);
}
struct sockaddr_in6 addr;
addr.sin6_family = AF_INET6;
addr.sin6_port = htons(5000);
inet_pton(AF_INET6, "::1", &addr.sin6_addr);
connect(sockfd, (struct sockaddr *)&addr, sizeof(addr));
stefanjaax marked this conversation as resolved.
Show resolved Hide resolved
close(sockfd);
}


void connectInet()
{
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0){
printf("\n Error : Could not create Inet socket \n");
exit(1);
}
struct sockaddr_in addr;
addr.sin_family = AF_INET;
connect(sockfd, (struct sockaddr *)&addr, sizeof(addr));
close(sockfd);
}

void connectNetlink()
{
int sockfd = socket(PF_NETLINK, SOCK_RAW, 0);
if(sockfd < 0){
printf("\n Error: Could not create netlink socket \n");
exit(1);
}
struct sockaddr_nl addr;
addr.nl_family = AF_NETLINK;
addr.nl_pid = getpid(); /* self pid */
connect(sockfd, (struct sockaddr *)&addr, sizeof(addr));
close(sockfd);
}

void connectUnix()
{
int sockfd = socket(PF_UNIX, SOCK_STREAM, 0);
if(sockfd < 0){
printf("\n Error: Could not create unix socket \n");
exit(1);
}
struct sockaddr_un addr;
memset(&addr, 0, sizeof(struct sockaddr_un));
addr.sun_family = AF_UNIX;
snprintf(addr.sun_path, UNIX_PATH_MAX, "./demo_socket");
connect(sockfd, (struct sockaddr *)&addr, sizeof(addr));
}

void connectPacket()
{
/* TODO: implement connect call for packet socket */
}

int main(int argc, char const *argv[])
{
if (argc != 2){
die_usage();
}
int i = atoi(argv[1]);
switch(i){
case AF_UNIX:
connectUnix();
break;
case AF_INET:
connectInet();
break;
case AF_INET6:
connectInet6();
break;
case AF_PACKET:
connectPacket();
break;
case AF_NETLINK:
connectNetlink();
break;
default:
die_usage();
}
/* code */
return 0;
}
1 change: 1 addition & 0 deletions hatrace.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ library
, unix
, unliftio
, unliftio-core
, wide-word
ghc-options: -Wall
default-language: Haskell2010

Expand Down
43 changes: 41 additions & 2 deletions src/System/Hatrace.hs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ module System.Hatrace
, SyscallExitDetails_exit(..)
, SyscallEnterDetails_exit_group(..)
, SyscallExitDetails_exit_group(..)
, SyscallEnterDetails_connect(..)
, SyscallExitDetails_connect(..)
, DetailedSyscallEnter(..)
, DetailedSyscallExit(..)
, ERRNO(..)
Expand Down Expand Up @@ -92,7 +94,7 @@ import qualified Data.Text.Encoding as T
import Data.Word (Word32, Word64)
import Foreign.C.Error (Errno(..), throwErrnoIfMinus1, throwErrnoIfMinus1_, getErrno, resetErrno, eCHILD, eINVAL)
import Foreign.C.String (peekCString)
import Foreign.C.Types (CInt(..), CLong(..), CULong(..), CChar(..), CSize(..))
import Foreign.C.Types (CInt(..), CUInt(..), CLong(..), CULong(..), CChar(..), CSize(..))
import Foreign.ForeignPtr (withForeignPtr)
import Foreign.Marshal.Alloc (alloca)
import Foreign.Marshal.Array (withArray)
Expand All @@ -107,6 +109,7 @@ import System.IO.Error (modifyIOError, ioeGetLocation, ioeSetLocation)
import System.Linux.Ptrace (TracedProcess(..), peekBytes, peekNullTerminatedBytes, peekNullWordTerminatedWords, detach)
import System.Linux.Ptrace.Syscall hiding (ptrace_syscall, ptrace_detach)
import qualified System.Linux.Ptrace.Syscall as Ptrace.Syscall
import qualified System.Linux.Ptrace as Ptrace
import System.Linux.Ptrace.Types (Regs(..))
import System.Linux.Ptrace.X86_64Regs (X86_64Regs(..))
import System.Linux.Ptrace.X86Regs (X86Regs(..))
Expand All @@ -122,7 +125,6 @@ import UnliftIO.IORef (newIORef, writeIORef, readIORef)
import System.Hatrace.SyscallTables.Generated (KnownSyscall(..), syscallName, syscallMap_i386, syscallMap_x64_64)
import System.Hatrace.Types


mapLeft :: (a1 -> a2) -> Either a1 b -> Either a2 b
mapLeft f = either (Left . f) Right

Expand Down Expand Up @@ -541,6 +543,19 @@ data SyscallExitDetails_faccessat = SyscallExitDetails_faccessat
{ enterDetail :: SyscallEnterDetails_faccessat
} deriving (Eq, Ord, Show)

data SyscallEnterDetails_connect = SyscallEnterDetails_connect
{ sockfd :: CInt
, addr :: Ptr Void
, addrlen :: CUInt
-- Peeked details
, sockAddr :: SockAddr
} deriving (Eq, Ord, Show)


data SyscallExitDetails_connect = SyscallExitDetails_connect
{ enterDetail :: SyscallEnterDetails_connect
, sockfd :: CInt
} deriving (Eq, Ord, Show)

data SyscallEnterDetails_execve = SyscallEnterDetails_execve
{ filename :: Ptr CChar
Expand All @@ -566,6 +581,7 @@ data DetailedSyscallEnter
| DetailedSyscallEnter_pipe SyscallEnterDetails_pipe
| DetailedSyscallEnter_pipe2 SyscallEnterDetails_pipe2
| DetailedSyscallEnter_access SyscallEnterDetails_access
| DetailedSyscallEnter_connect SyscallEnterDetails_connect
| DetailedSyscallEnter_faccessat SyscallEnterDetails_faccessat
| DetailedSyscallEnter_write SyscallEnterDetails_write
| DetailedSyscallEnter_read SyscallEnterDetails_read
Expand All @@ -587,6 +603,7 @@ data DetailedSyscallExit
| DetailedSyscallExit_pipe SyscallExitDetails_pipe
| DetailedSyscallExit_pipe2 SyscallExitDetails_pipe2
| DetailedSyscallExit_access SyscallExitDetails_access
| DetailedSyscallExit_connect SyscallExitDetails_connect
| DetailedSyscallExit_faccessat SyscallExitDetails_faccessat
| DetailedSyscallExit_write SyscallExitDetails_write
| DetailedSyscallExit_read SyscallExitDetails_read
Expand Down Expand Up @@ -772,6 +789,16 @@ getSyscallEnterDetails syscall syscallArgs pid = let proc = TracedProcess pid in
Syscall_exit -> do
let SyscallArgs{ arg0 = status } = syscallArgs
pure $ DetailedSyscallEnter_exit $ SyscallEnterDetails_exit { status = fromIntegral status }
Syscall_connect -> do
let SyscallArgs{ arg0 = sockfd, arg1 = addr, arg2 = addrLen} = syscallArgs
let addrPtr = word64ToPtr addr
sockAddr <- wrapPeekVariableLength (TracedProcess pid) (word64ToPtr addr) addrLen peekSockAddr
pure $ DetailedSyscallEnter_connect $ SyscallEnterDetails_connect
{ sockfd = fromIntegral sockfd
, addr = word64ToPtr addr
, addrlen = fromIntegral addrLen
, sockAddr = sockAddr
}
Syscall_exit_group -> do
let SyscallArgs{ arg0 = status } = syscallArgs
pure $ DetailedSyscallEnter_exit_group $ SyscallEnterDetails_exit_group { status = fromIntegral status }
Expand Down Expand Up @@ -886,6 +913,10 @@ getSyscallExitDetails knownSyscall syscallArgs pid = do
enterDetail@SyscallEnterDetails_exit_group{} -> do
pure $ DetailedSyscallExit_exit_group $ SyscallExitDetails_exit_group { enterDetail }

DetailedSyscallEnter_connect
enterDetail@SyscallEnterDetails_connect{} -> do
pure $ DetailedSyscallExit_connect $ SyscallExitDetails_connect { enterDetail, sockfd = fromIntegral result }

DetailedSyscallEnter_unimplemented syscall _syscallArgs ->
pure $ DetailedSyscallExit_unimplemented syscall syscallArgs result

Expand Down Expand Up @@ -983,6 +1014,10 @@ formatDetailedSyscallEnter = \case
SyscallEnterDetails_exit_group{ status } ->
"exit_group(" ++ show status ++ ")"

DetailedSyscallEnter_connect
SyscallEnterDetails_connect {sockfd, sockAddr, addrlen} ->
"connect(" ++ show sockfd ++ ", " ++ show sockAddr ++ ", " ++ show addrlen ++ ")"

DetailedSyscallEnter_unimplemented syscall syscallArgs ->
"unimplemented_syscall_details(" ++ show syscall ++ ", " ++ show syscallArgs ++ ")"

Expand Down Expand Up @@ -1071,6 +1106,10 @@ formatDetailedSyscallExit = \case
SyscallExitDetails_exit_group{ enterDetail = SyscallEnterDetails_exit_group{ status }} ->
"exit_group(" ++ show status ++ ")"

DetailedSyscallExit_connect
SyscallExitDetails_connect { enterDetail = SyscallEnterDetails_connect{sockfd, sockAddr, addrlen}} ->
"connect(" ++ show sockfd ++ show sockAddr ++ ", " ++ show addrlen ++ ") = " ++ show sockfd

DetailedSyscallExit_unimplemented syscall syscallArgs result ->
"unimplemented_syscall_details(" ++ show syscall ++ ", " ++ show syscallArgs ++ ") = " ++ show result

Expand Down
Loading