// Deallocates a Chunk, which means adding it to the delayed free list (or
 // Quarantine).
 void deallocate(void *UserPtr, uptr DeleteSize, AllocType Type) {
   if (UNLIKELY(!ThreadInited))
     initThread();
   // TODO(kostyak): see hook comment above
   // if (&__sanitizer_free_hook) __sanitizer_free_hook(UserPtr);
   if (!UserPtr)
     return;
   uptr ChunkBeg = reinterpret_cast<uptr>(UserPtr);
   if (!IsAligned(ChunkBeg, MinAlignment)) {
     dieWithMessage("ERROR: attempted to deallocate a chunk not properly "
                    "aligned at address %p\n", UserPtr);
   }
   ScudoChunk *Chunk =
       reinterpret_cast<ScudoChunk *>(ChunkBeg - ChunkHeaderSize);
   UnpackedHeader OldHeader;
   Chunk->loadHeader(&OldHeader);
   if (OldHeader.State != ChunkAllocated) {
     dieWithMessage("ERROR: invalid chunk state when deallocating address "
                    "%p\n", Chunk);
   }
   UnpackedHeader NewHeader = OldHeader;
   NewHeader.State = ChunkQuarantine;
   Chunk->compareExchangeHeader(&NewHeader, &OldHeader);
   if (DeallocationTypeMismatch) {
     // The deallocation type has to match the allocation one.
     if (NewHeader.AllocType != Type) {
       // With the exception of memalign'd Chunks, that can be still be free'd.
       if (NewHeader.AllocType != FromMemalign || Type != FromMalloc) {
         dieWithMessage("ERROR: allocation type mismatch on address %p\n",
                        Chunk);
       }
     }
   }
   uptr Size = NewHeader.RequestedSize;
   if (DeleteSizeMismatch) {
     if (DeleteSize && DeleteSize != Size) {
       dieWithMessage("ERROR: invalid sized delete on chunk at address %p\n",
                      Chunk);
     }
   }
   if (LIKELY(!ThreadTornDown)) {
     AllocatorQuarantine.Put(&ThreadQuarantineCache,
                             QuarantineCallback(&Cache), Chunk, Size);
   } else {
     SpinMutexLock l(&FallbackMutex);
     AllocatorQuarantine.Put(&FallbackQuarantineCache,
                             QuarantineCallback(&FallbackAllocatorCache),
                             Chunk, Size);
   }
 }
 // Returns the actual usable size of a chunk. Since this requires loading the
 // header, we will return it in the second parameter, as it can be required
 // by the caller to perform additional processing.
 uptr getUsableSize(const void *Ptr, UnpackedHeader *Header) {
   if (UNLIKELY(!ThreadInited))
     initThread();
   if (!Ptr)
     return 0;
   uptr ChunkBeg = reinterpret_cast<uptr>(Ptr);
   ScudoChunk *Chunk =
       reinterpret_cast<ScudoChunk *>(ChunkBeg - ChunkHeaderSize);
   Chunk->loadHeader(Header);
   // Getting the usable size of a chunk only makes sense if it's allocated.
   if (Header->State != ChunkAllocated) {
     dieWithMessage("ERROR: attempted to size a non-allocated chunk at "
                    "address %p\n", Chunk);
   }
   uptr Size =
       BackendAllocator.GetActuallyAllocatedSize(Chunk->AllocBeg(Header));
   // UsableSize works as malloc_usable_size, which is also what (AFAIU)
   // tcmalloc's MallocExtension::GetAllocatedSize aims at providing. This
   // means we will return the size of the chunk from the user beginning to
   // the end of the 'user' allocation, hence us subtracting the header size
   // and the offset from the size.
   if (Size == 0)
     return Size;
   return Size - ChunkHeaderSize - (Header->Offset << MinAlignmentLog);
 }
  // Allocates a chunk.
  void *allocate(uptr Size, uptr Alignment, AllocType Type) {
    if (UNLIKELY(!ThreadInited))
      initThread();
    if (!IsPowerOfTwo(Alignment)) {
      dieWithMessage("ERROR: malloc alignment is not a power of 2\n");
    }
    if (Alignment > MaxAlignment)
      return BackendAllocator.ReturnNullOrDie();
    if (Alignment < MinAlignment)
      Alignment = MinAlignment;
    if (Size == 0)
      Size = 1;
    if (Size >= MaxAllowedMallocSize)
      return BackendAllocator.ReturnNullOrDie();
    uptr RoundedSize = RoundUpTo(Size, MinAlignment);
    uptr ExtraBytes = ChunkHeaderSize;
    if (Alignment > MinAlignment)
      ExtraBytes += Alignment;
    uptr NeededSize = RoundedSize + ExtraBytes;
    if (NeededSize >= MaxAllowedMallocSize)
      return BackendAllocator.ReturnNullOrDie();

    void *Ptr;
    if (LIKELY(!ThreadTornDown)) {
      Ptr = BackendAllocator.Allocate(&Cache, NeededSize, MinAlignment);
    } else {
      SpinMutexLock l(&FallbackMutex);
      Ptr = BackendAllocator.Allocate(&FallbackAllocatorCache, NeededSize,
                               MinAlignment);
    }
    if (!Ptr)
      return BackendAllocator.ReturnNullOrDie();

    // If requested, we will zero out the entire contents of the returned chunk.
    if (ZeroContents && BackendAllocator.FromPrimary(Ptr))
       memset(Ptr, 0, BackendAllocator.GetActuallyAllocatedSize(Ptr));

    uptr AllocBeg = reinterpret_cast<uptr>(Ptr);
    uptr ChunkBeg = AllocBeg + ChunkHeaderSize;
    if (!IsAligned(ChunkBeg, Alignment))
      ChunkBeg = RoundUpTo(ChunkBeg, Alignment);
    CHECK_LE(ChunkBeg + Size, AllocBeg + NeededSize);
    ScudoChunk *Chunk =
        reinterpret_cast<ScudoChunk *>(ChunkBeg - ChunkHeaderSize);
    UnpackedHeader Header = {};
    Header.State = ChunkAllocated;
    Header.Offset = (ChunkBeg - ChunkHeaderSize - AllocBeg) >> MinAlignmentLog;
    Header.AllocType = Type;
    Header.RequestedSize = Size;
    Header.Salt = static_cast<u16>(Prng.Next());
    Chunk->storeHeader(&Header);
    void *UserPtr = reinterpret_cast<void *>(ChunkBeg);
    // TODO(kostyak): hooks sound like a terrible idea security wise but might
    //                be needed for things to work properly?
    // if (&__sanitizer_malloc_hook) __sanitizer_malloc_hook(UserPtr, Size);
    return UserPtr;
  }
 // Loads and unpacks the header, verifying the checksum in the process.
 static INLINE
 void loadHeader(const void *Ptr, UnpackedHeader *NewUnpackedHeader) {
   PackedHeader NewPackedHeader =
       atomic_load_relaxed(getConstAtomicHeader(Ptr));
   *NewUnpackedHeader = bit_cast<UnpackedHeader>(NewPackedHeader);
   if (UNLIKELY(NewUnpackedHeader->Checksum !=
       computeChecksum(Ptr, NewUnpackedHeader)))
     dieWithMessage("corrupted chunk header at address %p\n", Ptr);
 }
 // Chunk recycling function, returns a quarantined chunk to the backend.
 void Recycle(ScudoChunk *Chunk) {
   UnpackedHeader Header;
   Chunk->loadHeader(&Header);
   if (Header.State != ChunkQuarantine) {
     dieWithMessage("ERROR: invalid chunk state when recycling address %p\n",
                    Chunk);
   }
   void *Ptr = Chunk->AllocBeg(&Header);
   getAllocator().Deallocate(Cache_, Ptr);
 }
 // Packs and stores the header, computing the checksum in the process. We
 // compare the current header with the expected provided one to ensure that
 // we are not being raced by a corruption occurring in another thread.
 static INLINE void compareExchangeHeader(void *Ptr,
                                          UnpackedHeader *NewUnpackedHeader,
                                          UnpackedHeader *OldUnpackedHeader) {
   NewUnpackedHeader->Checksum = computeChecksum(Ptr, NewUnpackedHeader);
   PackedHeader NewPackedHeader = bit_cast<PackedHeader>(*NewUnpackedHeader);
   PackedHeader OldPackedHeader = bit_cast<PackedHeader>(*OldUnpackedHeader);
   if (UNLIKELY(!atomic_compare_exchange_strong(
           getAtomicHeader(Ptr), &OldPackedHeader, NewPackedHeader,
           memory_order_relaxed)))
     dieWithMessage("race on chunk header at address %p\n", Ptr);
 }
Beispiel #7
0
void initFlags() {
  SetCommonFlagsDefaults();
  {
    CommonFlags cf;
    cf.CopyFrom(*common_flags());
    cf.exitcode = 1;
    OverrideCommonFlags(cf);
  }
  Flags *f = getFlags();
  f->setDefaults();

  FlagParser scudo_parser;
  RegisterScudoFlags(&scudo_parser, f);
  RegisterCommonFlags(&scudo_parser);

  scudo_parser.ParseString(GetEnv("SCUDO_OPTIONS"));

  InitializeCommonFlags();

  // Sanity checks and default settings for the Quarantine parameters.

  if (f->QuarantineSizeMb < 0) {
    const int DefaultQuarantineSizeMb = 64;
    f->QuarantineSizeMb = DefaultQuarantineSizeMb;
  }
  // We enforce an upper limit for the quarantine size of 4Gb.
  if (f->QuarantineSizeMb > (4 * 1024)) {
    dieWithMessage("ERROR: the quarantine size is too large\n");
  }
  if (f->ThreadLocalQuarantineSizeKb < 0) {
    const int DefaultThreadLocalQuarantineSizeKb = 1024;
    f->ThreadLocalQuarantineSizeKb = DefaultThreadLocalQuarantineSizeKb;
  }
  // And an upper limit of 128Mb for the thread quarantine cache.
  if (f->ThreadLocalQuarantineSizeKb > (128 * 1024)) {
    dieWithMessage("ERROR: the per thread quarantine cache size is too "
                   "large\n");
  }
}
 // Reallocates a chunk. We can save on a new allocation if the new requested
 // size still fits in the chunk.
 void *reallocate(void *OldPtr, uptr NewSize) {
   if (UNLIKELY(!ThreadInited))
     initThread();
   UnpackedHeader OldHeader;
   uptr Size = getUsableSize(OldPtr, &OldHeader);
   uptr ChunkBeg = reinterpret_cast<uptr>(OldPtr);
   ScudoChunk *Chunk =
       reinterpret_cast<ScudoChunk *>(ChunkBeg - ChunkHeaderSize);
   if (OldHeader.AllocType != FromMalloc) {
     dieWithMessage("ERROR: invalid chunk type when reallocating address %p\n",
                    Chunk);
   }
   UnpackedHeader NewHeader = OldHeader;
   // The new size still fits in the current chunk.
   if (NewSize <= Size) {
     NewHeader.RequestedSize = NewSize;
     Chunk->compareExchangeHeader(&NewHeader, &OldHeader);
     return OldPtr;
   }
   // Otherwise, we have to allocate a new chunk and copy the contents of the
   // old one.
   void *NewPtr = allocate(NewSize, MinAlignment, FromMalloc);
   if (NewPtr) {
     uptr OldSize = OldHeader.RequestedSize;
     memcpy(NewPtr, OldPtr, Min(NewSize, OldSize));
     NewHeader.State = ChunkQuarantine;
     Chunk->compareExchangeHeader(&NewHeader, &OldHeader);
     if (LIKELY(!ThreadTornDown)) {
       AllocatorQuarantine.Put(&ThreadQuarantineCache,
                               QuarantineCallback(&Cache), Chunk, OldSize);
     } else {
       SpinMutexLock l(&FallbackMutex);
       AllocatorQuarantine.Put(&FallbackQuarantineCache,
                               QuarantineCallback(&FallbackAllocatorCache),
                               Chunk, OldSize);
     }
   }
   return NewPtr;
 }
int main(int argc, char **argv)
{
    if (argc != 6)
        dieWithMessage("Usage: Host Service UserWords Nagle-Choice Cork-Choice\n");

    char *host = argv[1];
    char *service = argv[2];
    char *sendStr = argv[3];
	int nagleChoice = atoi(argv[4]);
	int corkChoice = atoi(argv[5]);

    struct addrinfo hints;
    struct addrinfo *res;
    memset(&hints, 0, sizeof(hints));

    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = 0;
    hints.ai_flags = AI_PASSIVE;

    int retVal = getaddrinfo(host, service, &hints, &res);

    if(retVal != 0)
        dieWithMessage(gai_strerror(retVal));

    int sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);

    if(sock < 0)
        dieWithMessage("socket: failed\n");

    if (connect(sock, res->ai_addr, res->ai_addrlen) < 0)
        dieWithMessage("connect : failed\n");

    int sendBytesCount = strlen(sendStr);
    int i = 0;
	char sendBuf[1];

	//设置nagle、cork算法
	retVal = setsockopt(sock, IPPROTO_TCP, TCP_CORK, &corkChoice, sizeof(corkChoice));

	if(retVal == -1)
		dieWithMessage("setsockopt : failed\n");

	retVal = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &nagleChoice, sizeof(nagleChoice));

	if(retVal == -1)
		dieWithMessage("setsockopt : failed\n");

    for(i=0; i<sendBytesCount; i++)
    {
		sendBuf[0] = sendStr[i];
        ssize_t sentBytes = send(sock, sendBuf, 1, 0);
        if (sentBytes < 0)
            dieWithMessage("send : failed\n");
        else if (sentBytes != 1)
            dieWithMessage("send : exception\n");
    }

    freeaddrinfo(res);

    close(sock);

    return 0;
}
int tryPassword(char *guess, int sock, struct addrinfo *servAddr, int i, int j)
{
  
  int position = 0;

  while(position < strlen(options))
  {
  	guess[i] = options[position];

  	struct sockaddr_storage fromAddr; // Source address of IPaddress

  	// Set length of from address structure (in-out parameter)
  	socklen_t fromAddrLen = sizeof(fromAddr);

  	guesses += 1;
    guess[j + 1] = '\0';
   
  	ssize_t numBytes = sendto(sock, guess, j+1, 0, servAddr->ai_addr, servAddr->ai_addrlen);
  	if (numBytes < 0)
      dieWithMessage("sendto() failed");
  	else if (numBytes != j+1)
      dieWithMessage("sendto() error, sent unexpected number of bytes");

  	char message[2];
  	//starting timeout check
    struct pollfd fd;
    int res;
    
    fd.fd = sock;
    fd.events = POLLIN;
    res = poll(&fd, 1, 1000); // 1000 ms timeout
    if(res == 0)
    {
       printf("Connection timeout, continuing to next iteration.\n");
       int next_length = i + 1;
       if(next_length <= j)
       {
          if(tryPassword(guess, sock, servAddr, next_length, j) == 0)
          {
           position++;
          }
          else
          {
           return 1;
          }
       }
       else
       {
          position++;
       }
    }
    else if(res == -1)
    {
      dieWithMessage("connection Error, client closing");
    }
    else
    {
 	    //recieving from server
 	    numBytes = recv(sock, message, 1, 0); //returning from server, 0 = success, 1 = failure, 2 = timeout
 	    if (numBytes < 0)
            dieWithMessage("recvfrom() failed");
        else if (numBytes != 1)
            dieWithMessage("recvfrom() error, received unexpected number of bytes");
  	    //printf("message is: %s\n", message);
        message[1] = '\0';

  	 if(strcmp(message, "0") == 0)
  	 {
  	   printf("Password guessed! The password was %s\n", guess);
  	   return 0;
     }
      if(strcmp(message, "1") == 0)
      {
    	 int next_length = i + 1;
    	 if(next_length <= j)
    	 {
    		  if(tryPassword(guess, sock, servAddr, next_length, j) == 0)
    		  {
    			 position++;
    		  }
    		  else
    		  {
    			 return 1;
    		  }
    	 }
    	 else
    	 {
    		  position++;
    	 }
    }
    }

  }
    return 0;
}
int main(int argc, char *argv[]) {
                                
  signal(SIGINT, ExitHandler);   //signal handler and a start time to track programs runtime
  start_time = clock();


  if (argc != 4) // Test for correct number of arguments
  {
  	dieWithMessage("3 arguments required, Server Name(IP address), Server Port(between 5k and 10k), and a password length of 1-8\n");
  }



  char *IPaddress = argv[1];     // First arg: Server's IP address

  //Checking for legal port
  char *originalport = argv[2]; // 2nd argument: Port
  int port = atoi(originalport);
  while(port < 5000 || port > 10000)
  {
    printf("port invalid, please choose a number between 5000 and 10000: ");
    scanf("%d", &port);
  }
  char servPort[6];
  sprintf(servPort, "%d", port);

  int length = atoi(argv[3]);// 3rd argument: password Length
  while(length < 1 || length > 8)
  {
    printf("Length invalid, please enter a number between 1 and 8: ");
    scanf("%d", &length);
  }

  
  
  int found = 1;
  char *guess = malloc(sizeof(char)*(length+1));
  int i = 0;
  int j = length - 1;

   

  // Tell the system what kind(s) of address info we want
  struct addrinfo addrCriteria;                   // Criteria for address match
  memset(&addrCriteria, 0, sizeof(addrCriteria)); // Zero out structure
  addrCriteria.ai_family = AF_UNSPEC;             // Any address family
  addrCriteria.ai_socktype = SOCK_DGRAM;          // Only datagram sockets
  addrCriteria.ai_protocol = IPPROTO_UDP;         // Only UDP protocol

  // Get address(es)
  struct addrinfo *servAddr; // List of IPaddress addresses
  int rtnVal = getaddrinfo(IPaddress, servPort, &addrCriteria, &servAddr);
  if (rtnVal != 0)
    dieWithMessage("getaddrinfo() failed");

  // Create a datagram/UDP socket
  int sock = socket(servAddr->ai_family, servAddr->ai_socktype, servAddr->ai_protocol); // Socket descriptor for client
  if (sock < 0)
    dieWithMessage("socket() failed");
  
  int thing = tryPassword(guess, sock, servAddr, i, j);
  
  if(thing == 0)
  {
  printf("The password was found in %lu guesses!\n", guesses);
  stop_time = clock();
  printf("Elapsed time: %lf microseconds\n", (double)(stop_time - start_time));
  }
  else
  {
    printf("The password was not guessed after %lu guesses!\n", guesses);
    stop_time = clock();
    printf("Elapsed time: %lf microseconds\n", (double)(stop_time - start_time));
    freeaddrinfo(servAddr);
  }

  close(sock);
  exit(0);
}