Advertisement
EXTREMEXPLOIT

Threaded Bank

Mar 5th, 2021 (edited)
223
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.00 KB | None | 0 0
  1. #include <pthread.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <stdbool.h>
  5. #include <unistd.h>
  6. #include <sys/file.h>
  7. #include <sys/wait.h>
  8. #include <semaphore.h>
  9. #include "myutils.h"
  10.  
  11. #define NOPERATIONS 1000
  12. #define FILENAME "Bank.dat"
  13. #define NACCOUNTS 10
  14. #define NTHREADS 250
  15. #define INITIAL_ACCOUNT_MONEY 100
  16.  
  17. int SOLUTION = 0; // La Solution 1 es usando FileLocks y la Solution 2 es con Semáforos.
  18. int fbank; // Archivo Bank.dat
  19.  
  20. typedef struct account { int ID; double Balance; } Account; // Estructura de nuestra cuenta bancaria.
  21.  
  22. sem_t* NamedMutex;
  23.  
  24. void doSomething() { for (int i=0; i < 100000; i++); }
  25.  
  26. void bankInit(){
  27.     for(int i=0; i<NACCOUNTS; i++) {
  28.         Account CurrentAccount = {.ID = i, .Balance = INITIAL_ACCOUNT_MONEY}; // Iniciamos la cuenta.
  29.         write(fbank, &CurrentAccount, sizeof(Account)); // Escribimos nuestra cuenta en el Bank.dat
  30.     }
  31. }
  32.  
  33. void fileWithdraw(int accountID, double amount){
  34.     Account tempAccount;
  35.     lseek(fbank, accountID * sizeof(Account), SEEK_SET);
  36.     read(fbank, &tempAccount, sizeof(Account));
  37.  
  38.     tempAccount.Balance -= amount;
  39.  
  40.     lseek(fbank, accountID * sizeof(Account), SEEK_SET);
  41.     write(fbank, &tempAccount, sizeof(Account));
  42. }
  43.  
  44. void fileDeposit(int accountID, double amount){
  45.     Account tempAccount;
  46.     lseek(fbank, accountID * sizeof(Account), SEEK_SET);
  47.     read(fbank, &tempAccount, sizeof(Account));
  48.  
  49.     tempAccount.Balance += amount;
  50.  
  51.     lseek(fbank, accountID * sizeof(Account), SEEK_SET);
  52.     write(fbank, &tempAccount, sizeof(Account));
  53. }
  54.  
  55. bool check(Account* acc, double amount) { return acc->Balance - amount >= 0; }
  56.  
  57. bool fileCheck(int accountID, double amount){
  58.     Account tempAccount;
  59.     lseek(fbank, accountID * sizeof(Account), SEEK_SET);
  60.     read(fbank, &tempAccount, sizeof(Account));
  61.     return check(&tempAccount, amount);
  62. }
  63.  
  64. bool withdraw(int accountID, double amount) {
  65.     if(fileCheck(accountID, amount))  {
  66.         fileWithdraw(accountID, amount);
  67.         doSomething();
  68.         return true;
  69.     }
  70.     return false;
  71. }
  72.  
  73. void deposit(int accountID, double amount) {
  74.     fileDeposit(accountID, amount);
  75.     doSomething();
  76. }
  77.  
  78. bool transfer1(int fromID, int toID, double amount){
  79.     // Solución usando FileLocks.
  80.  
  81.     int Lock1, Lock2; // Con esto vamos a evitar posibles Deadlocks.
  82.     if (fromID > toID) {Lock1 = toID * sizeof(Account); Lock2 = fromID * sizeof(Account); }
  83.     else{ Lock1 = fromID * sizeof(Account), Lock2 = toID * sizeof(Account); }
  84.  
  85.     while(file_lock(fbank, Lock1, sizeof(Account)) < 0);
  86.     while(file_lock(fbank, Lock2, sizeof(Account)) < 0);
  87.  
  88.     // En este momento, ya hemos hecho el lock de la zona determinada de nuestro archivo.
  89.     // Así que ya podemos hacer la operación de sumar y restar dinero.
  90.     bool isDone = withdraw(fromID, amount);
  91.     if (isDone) { deposit(toID, amount); }
  92.  
  93.     file_unlock(fbank, Lock1, sizeof(Account));
  94.     file_unlock(fbank, Lock2, sizeof(Account));
  95.  
  96.     return isDone;
  97. }
  98.  
  99. bool transfer2(int fromID, int toID, double amount){
  100.     // Solución usando semáforos.
  101.  
  102.     sem_wait(NamedMutex);
  103.  
  104.     bool isDone = withdraw(fromID, amount);
  105.     if (isDone) { deposit(toID, amount); }
  106.  
  107.     sem_post(NamedMutex);
  108.  
  109.     return isDone;
  110. }
  111.  
  112. void* tranferThread(){
  113.     fbank = open("Bank.dat",  O_RDWR, 0600);
  114.     int iter = NOPERATIONS/NACCOUNTS;
  115.     int fromID = -1, toID = -1;
  116.     while(iter--) {
  117.         fromID = -1; toID = -1;
  118.         while(fromID == toID) { // Si hemos seleccionado aleatoriamente las mismas cuentas, repetimos el proceso.
  119.             fromID = rand()%NACCOUNTS; toID = rand()%NACCOUNTS;
  120.         }
  121.  
  122.         double randomAmount = rand()%50+1;
  123.         printf("ID: %d --- %d€ ---> ID: %d \n", fromID, (int) randomAmount, toID);
  124.         if (SOLUTION == 1) transfer1(fromID, toID, randomAmount);
  125.         else if (SOLUTION == 2) transfer2(fromID, toID, randomAmount);
  126.  
  127.     }
  128.     return NULL;
  129. }
  130.  
  131. int main(int argc, char* argv[]){
  132.     if (argc > 1) SOLUTION = atoi(argv[1]);
  133.     startTimer(0);
  134.     if (SOLUTION == 1 || SOLUTION == 2){
  135.         pthread_t ThreadsID[NTHREADS];
  136.         fbank = open(FILENAME, O_CREAT | O_RDWR, 0600);
  137.         if (SOLUTION == 2) NamedMutex = sem_open("/NamedMutex", O_CREAT, 0644, 1);
  138.         bankInit();
  139.         printf("----> Initial Bank Total Money: %d€ <----\n", INITIAL_ACCOUNT_MONEY);
  140.         if (SOLUTION == 1){
  141.             for (int i=0; i < NTHREADS; i++){
  142.                 int PID = fork();
  143.                 if (PID == 0){
  144.                     tranferThread();
  145.                     exit(0);
  146.                 }
  147.             }
  148.             while(wait(NULL) > 0);
  149.         }
  150.         else if (SOLUTION == 2){
  151.             for(int i=0; i<NTHREADS; i++) { pthread_create(&ThreadsID[i], NULL, tranferThread, NULL); }
  152.             for(int i=0; i<NTHREADS; i++) { pthread_join(ThreadsID[i], NULL); }
  153.         }
  154.  
  155.         sem_close(NamedMutex);
  156.         close(fbank);
  157.  
  158.         printf("Time: %ld ms\n", endTimer(0));
  159.         return 0;
  160.     }
  161.     else return -1;
  162. }
  163.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement