diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea050e9 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +._* diff --git a/Bonus-DeadDrop/.gitignore b/Bonus-DeadDrop/.gitignore new file mode 100644 index 0000000..44c320d --- /dev/null +++ b/Bonus-DeadDrop/.gitignore @@ -0,0 +1,3 @@ +/*.o +/sender +/receiver diff --git a/Part2-DeadDrop/Makefile b/Bonus-DeadDrop/Makefile similarity index 100% rename from Part2-DeadDrop/Makefile rename to Bonus-DeadDrop/Makefile diff --git a/Bonus-DeadDrop/receiver.c b/Bonus-DeadDrop/receiver.c new file mode 100755 index 0000000..cf60232 --- /dev/null +++ b/Bonus-DeadDrop/receiver.c @@ -0,0 +1,29 @@ + +#include"util.h" +// mman library to be used for hugepage allocations (e.g. mmap or posix_memalign only) +#include + +int main(int argc, char **argv) +{ + // [Bonus] TODO: Put your covert channel setup code here + + printf("Please press enter.\n"); + + char text_buf[2]; + fgets(text_buf, sizeof(text_buf), stdin); + + printf("Receiver now listening.\n"); + + bool listening = true; + while (listening) { + + // [Bonus] TODO: Put your covert channel code here + + } + + printf("Receiver finished.\n"); + + return 0; +} + + diff --git a/Bonus-DeadDrop/sender.c b/Bonus-DeadDrop/sender.c new file mode 100755 index 0000000..ebbb973 --- /dev/null +++ b/Bonus-DeadDrop/sender.c @@ -0,0 +1,47 @@ + +#include"util.h" +// mman library to be used for hugepage allocations (e.g. mmap or posix_memalign only) +#include + +// [Bonus] TODO: define your own buffer size +#define BUFF_SIZE (1<<21) +//#define BUFF_SIZE TODO + +int main(int argc, char **argv) +{ + // Allocate a buffer using huge page + // See the handout for details about hugepage management + void *buf= mmap(NULL, BUFF_SIZE, PROT_READ | PROT_WRITE, MAP_POPULATE | + MAP_ANONYMOUS | MAP_PRIVATE | MAP_HUGETLB, -1, 0); + + if (buf == (void*) - 1) { + perror("mmap() error\n"); + exit(EXIT_FAILURE); + } + // The first access to a page triggers overhead associated with + // page allocation, TLB insertion, etc. + // Thus, we use a dummy write here to trigger page allocation + // so later access will not suffer from such overhead. + *((char *)buf) = 1; // dummy write to trigger page allocation + + + // [Bonus] TODO: + // Put your covert channel setup code here + + printf("Please type a message.\n"); + + bool sending = true; + while (sending) { + char text_buf[128]; + fgets(text_buf, sizeof(text_buf), stdin); + + // [Bonus] TODO: + // Put your covert channel code here + + } + + printf("Sender finished.\n"); + return 0; +} + + diff --git a/Bonus-DeadDrop/util.c b/Bonus-DeadDrop/util.c new file mode 100755 index 0000000..0c44ebb --- /dev/null +++ b/Bonus-DeadDrop/util.c @@ -0,0 +1,102 @@ + +#include "util.h" + +/* Measure the time it takes to access a block with virtual address addr. */ +CYCLES measure_one_block_access_time(ADDR_PTR addr) +{ + CYCLES cycles; + + asm volatile("mov %1, %%r8\n\t" + "lfence\n\t" + "rdtsc\n\t" + "mov %%eax, %%edi\n\t" + "mov (%%r8), %%r8\n\t" + "lfence\n\t" + "rdtsc\n\t" + "sub %%edi, %%eax\n\t" + : "=a"(cycles) /*output*/ + : "r"(addr) + : "r8", "edi"); + + return cycles; +} + +/* + * CLFlushes the given address. + * + * Note: clflush is provided to help you debug and should not be used in your + * final submission + */ +void clflush(ADDR_PTR addr) +{ + asm volatile ("clflush (%0)"::"r"(addr)); +} + +/* + * Converts a string to its binary representation. + */ +char *string_to_binary(char *s) +{ + if (s == NULL) + return 0; /* no input string */ + + size_t len = strlen(s); + + // Each char is one byte (8 bits) and + 1 at the end for null terminator + char *binary = malloc(len * 8 + 1); + binary[len] = '\0'; + + for (size_t i = 0; i < len; ++i) + { + char ch = s[i]; + for (int j = 7; j >= 0; --j) + { + if (ch & (1 << j)) + { + strcat(binary, "1"); + } + else + { + strcat(binary, "0"); + } + } + } + + return binary; +} + +/* + * Converts a binary string to its ASCII representation. + */ +char *binary_to_string(char *data) +{ + // Each char is 8 bits + size_t msg_len = strlen(data) / 8; + + // Add one for null terminator at the end + char *msg = malloc(msg_len + 1); + msg[msg_len] = '\0'; + + for (int i = 0; i < msg_len; i++) + { + char tmp[8]; + int k = 0; + + for (int j = i * 8; j < ((i + 1) * 8); j++) + { + tmp[k++] = data[j]; + } + + msg[i] = strtol(tmp, 0, 2); + } + + return msg; +} + +/* + * Converts a string to integer + */ +int string_to_int(char* s) +{ + return atoi(s); +} diff --git a/Part2-DeadDrop/util.h b/Bonus-DeadDrop/util.h similarity index 100% rename from Part2-DeadDrop/util.h rename to Bonus-DeadDrop/util.h diff --git a/Part1-Timing/.gitignore b/Part1-Timing/.gitignore new file mode 100644 index 0000000..578ca3c --- /dev/null +++ b/Part1-Timing/.gitignore @@ -0,0 +1,3 @@ +/main +/main-visual +/data \ No newline at end of file diff --git a/Part1-Timing/Makefile b/Part1-Timing/Makefile index 5bc5f7a..c38e3a6 100644 --- a/Part1-Timing/Makefile +++ b/Part1-Timing/Makefile @@ -1,16 +1,19 @@ include ../cpu.mk -all: main +all: main main-visual run: main @taskset -c $(SENDER_CPU) ./main -run-reference: reference - @taskset -c $(SENDER_CPU) ./reference +run-visual: main-visual + @taskset -c $(SENDER_CPU) ./main-visual main: main.c Makefile @gcc main.c -o main +main-visual: main.c Makefile + @gcc main.c -DVISUAL -o main-visual + .PHONY: clean clean: diff --git a/Part1-Timing/main.c b/Part1-Timing/main.c index 1b6fa97..84e4b4f 100644 --- a/Part1-Timing/main.c +++ b/Part1-Timing/main.c @@ -1,9 +1,17 @@ #include "utility.h" -// TODO: Uncomment the following lines and fill in the correct size -//#define L1_SIZE [TODO] -//#define L2_SIZE [TODO] -//#define L3_SIZE [TODO] +#ifndef VISUAL +#define PRINT_FUNC print_results_plaintext +#else +#define PRINT_FUNC print_results_for_visualization +#endif + +#define LINE_SIZE 64 +// [1.2] TODO: Uncomment the following lines and fill in the correct size +//#define L1_SIZE TODO +//#define L2_SIZE TODO +//#define L3_SIZE TODO +//#define BUFF_SIZE TODO int main (int ac, char **av) { @@ -15,14 +23,12 @@ int main (int ac, char **av) { uint64_t l3_latency[SAMPLES] = {0}; // A temporary variable we can use to load addresses - // The volatile keyword tells the compiler to not put this variable into a - // register- it should always try to load from memory/ cache. - volatile char tmp; + uint8_t tmp; - // Allocate a buffer of 64 Bytes - // the size of an unsigned integer (uint64_t) is 8 Bytes - // Therefore, we request 8 * 8 Bytes - uint64_t *target_buffer = (uint64_t *)malloc(8*sizeof(uint64_t)); + // Allocate a buffer of LINE_SIZE Bytes + // The volatile keyword tells the compiler to not put this variable into a + // register -- it should always try to be loaded from memory / cache. + volatile uint8_t *target_buffer = (uint8_t *)malloc(LINE_SIZE); if (NULL == target_buffer) { perror("Unable to malloc"); @@ -31,11 +37,12 @@ int main (int ac, char **av) { // [1.2] TODO: Uncomment the following line to allocate a buffer of a size // of your chosing. This will help you measure the latencies at L2 and L3. - //uint64_t *eviction_buffer = (uint64_t)malloc(TODO); + //volatile uint8_t *eviction_buffer = (uint8_t *)malloc(BUFF_SIZE); // Example: Measure L1 access latency, store results in l1_latency array for (int i=0; i - -int main(int argc, char **argv) -{ - // Put your covert channel setup code here - - printf("Please press enter.\n"); - - char text_buf[2]; - fgets(text_buf, sizeof(text_buf), stdin); - - printf("Receiver now listening.\n"); - - bool listening = true; - while (listening) { - - // Put your covert channel code here - - } - - printf("Receiver finished.\n"); - - return 0; -} - - diff --git a/Part2-DeadDrop/sender.c b/Part2-DeadDrop/sender.c deleted file mode 100755 index d196515..0000000 --- a/Part2-DeadDrop/sender.c +++ /dev/null @@ -1,45 +0,0 @@ - -#include"util.h" -// mman library to be used for hugepage allocations (e.g. mmap or posix_memalign only) -#include - -// TODO: define your own buffer size -#define BUFF_SIZE (1<<21) -//#define BUFF_SIZE [TODO] - -int main(int argc, char **argv) -{ - // Allocate a buffer using huge page - // See the handout for details about hugepage management - void *buf= mmap(NULL, BUFF_SIZE, PROT_READ | PROT_WRITE, MAP_POPULATE | MAP_ANONYMOUS | MAP_PRIVATE | MAP_HUGETLB, -1, 0); - - if (buf == (void*) - 1) { - perror("mmap() error\n"); - exit(EXIT_FAILURE); - } - // The first access to a page triggers overhead associated with - // page allocation, TLB insertion, etc. - // Thus, we use a dummy write here to trigger page allocation - // so later access will not suffer from such overhead. - //*((char *)buf) = 1; // dummy write to trigger page allocation - - - // TODO: - // Put your covert channel setup code here - - printf("Please type a message.\n"); - - bool sending = true; - while (sending) { - char text_buf[128]; - fgets(text_buf, sizeof(text_buf), stdin); - - // TODO: - // Put your covert channel code here - } - - printf("Sender finished.\n"); - return 0; -} - - diff --git a/Part2-DeadDrop/util.c b/Part2-DeadDrop/util.c deleted file mode 100755 index 56bbe0b..0000000 --- a/Part2-DeadDrop/util.c +++ /dev/null @@ -1,102 +0,0 @@ - -#include "util.h" - -/* Measure the time it takes to access a block with virtual address addr. */ -CYCLES measure_one_block_access_time(ADDR_PTR addr) -{ - CYCLES cycles; - - asm volatile("mov %1, %%r8\n\t" - "lfence\n\t" - "rdtsc\n\t" - "mov %%eax, %%edi\n\t" - "mov (%%r8), %%r8\n\t" - "lfence\n\t" - "rdtsc\n\t" - "sub %%edi, %%eax\n\t" - : "=a"(cycles) /*output*/ - : "r"(addr) - : "r8", "edi"); - - return cycles; -} - -/* - * CLFlushes the given address. - * - * Note: clflush is provided to help you debug and should not be used in your - * final submission - */ -void clflush(ADDR_PTR addr) -{ - asm volatile ("clflush (%0)"::"r"(addr)); -} - -/* - * Converts a string to its binary representation. - */ -char *string_to_binary(char *s) -{ - if (s == NULL) - return 0; /* no input string */ - - size_t len = strlen(s); - - // Each char is one byte (8 bits) and + 1 at the end for null terminator - char *binary = malloc(len * 8 + 1); - binary[len] = '\0'; - - for (size_t i = 0; i < len; ++i) - { - char ch = s[i]; - for (int j = 7; j >= 0; --j) - { - if (ch & (1 << j)) - { - strcat(binary, "1"); - } - else - { - strcat(binary, "0"); - } - } - } - - return binary; -} - -/* - * Converts a binary string to its ASCII representation. - */ -char *binary_to_string(char *data) -{ - // Each char is 8 bits - size_t msg_len = strlen(data) / 8; - - // Add one for null terminator at the end - char *msg = malloc(msg_len + 1); - msg[msg_len] = '\0'; - - for (int i = 0; i < msg_len; i++) - { - char tmp[8]; - int k = 0; - - for (int j = i * 8; j < ((i + 1) * 8); j++) - { - tmp[k++] = data[j]; - } - - msg[i] = strtol(tmp, 0, 2); - } - - return msg; -} - -/* - * Converts a string to integer - */ -int string_to_int(char* s) -{ - return atoi(s); -} diff --git a/Part2-FlushReload/.gitignore b/Part2-FlushReload/.gitignore new file mode 100644 index 0000000..4c6a43e --- /dev/null +++ b/Part2-FlushReload/.gitignore @@ -0,0 +1,3 @@ +/shared_file +/*.o +/attacker diff --git a/Part2-FlushReload/Makefile b/Part2-FlushReload/Makefile new file mode 100644 index 0000000..567b739 --- /dev/null +++ b/Part2-FlushReload/Makefile @@ -0,0 +1,26 @@ +include ../cpu.mk + +TARGETS=attacker +UTILS=util.o + +all: $(TARGETS) + +$(UTILS): %.o: %.c %.h + $(CC) $(CFLAGS) -c $< + +%.o: %.c util.h + $(CC) $(CFLAGS) -c $< + +$(TARGETS): %:%.o util.o + $(CC) $(CFLAGS) $^ -o $@ + +run_victim: + taskset -c $(SENDER_CPU) ./victim + +run_attacker: attacker + taskset -c $(RECEIVER_CPU) ./attacker + +.PHONY: clean + +clean: + $(RM) *.o $(HELPERS) $(TARGETS) diff --git a/Part2-FlushReload/attacker.c b/Part2-FlushReload/attacker.c new file mode 100644 index 0000000..e85b3a1 --- /dev/null +++ b/Part2-FlushReload/attacker.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "util.h" + + +int main() { + int flag = -1; + + // buf is shared between the attacker and the victim + char *buf = allocate_shared_buffer(); + + // [2.1] TODO: Put your capture-the-flag code here + + printf("Flag: %d\n", flag); + + deallocate_shared_buffer(buf); + return 0; +} \ No newline at end of file diff --git a/Part2-FlushReload/gen_file.py b/Part2-FlushReload/gen_file.py new file mode 100644 index 0000000..fc87690 --- /dev/null +++ b/Part2-FlushReload/gen_file.py @@ -0,0 +1,11 @@ +from pathlib import Path + + +def main(): + out_path = Path("shared_file") + with out_path.open(mode="wb"): + out_path.write_bytes(bytearray([0] * 1024 * 128)) + + +if __name__ == '__main__': + main() diff --git a/Part2-FlushReload/util.c b/Part2-FlushReload/util.c new file mode 100755 index 0000000..616ee59 --- /dev/null +++ b/Part2-FlushReload/util.c @@ -0,0 +1,98 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "util.h" + +/* Measure the time it takes to access a block with virtual address addr. */ +CYCLES measure_one_block_access_time(ADDR_PTR addr) +{ + CYCLES cycles; + + asm volatile("mov %1, %%r8\n\t" + "lfence\n\t" + "rdtsc\n\t" + "mov %%eax, %%edi\n\t" + "mov (%%r8), %%r8\n\t" + "lfence\n\t" + "rdtsc\n\t" + "sub %%edi, %%eax\n\t" + : "=a"(cycles) /*output*/ + : "r"(addr) + : "r8", "edi"); + + return cycles; +} + +/* + * CLFlushes the given address. + * + * Note: clflush is provided to help you debug and should not be used in your + * final submission + */ +void clflush(ADDR_PTR addr) +{ + asm volatile ("clflush (%0)"::"r"(addr)); +} + +int fd; +size_t file_size; + +char *allocate_shared_buffer() { + const char *filepath = "shared_file"; + + int fd = open(filepath, O_RDONLY, (mode_t)0600); + + if (fd == -1) + { + perror("Error opening file for writing, please run `python3 gen_file.py` to get the file for shared buf"); + exit(EXIT_FAILURE); + } + + struct stat fileInfo = {0}; + + if (fstat(fd, &fileInfo) == -1) + { + perror("Error getting the file size"); + exit(EXIT_FAILURE); + } + + if (fileInfo.st_size == 0) + { + fprintf(stderr, "Error: File is empty, nothing to do\n"); + exit(EXIT_FAILURE); + } + + if (fileInfo.st_size < SEC_RANGE * ALIGN) { + close(fd); + perror("File is too small\n"); + exit(EXIT_FAILURE); + } + + char *buf = mmap(0, fileInfo.st_size, PROT_READ, MAP_SHARED, fd, 0); + if (buf == MAP_FAILED) + { + close(fd); + perror("Error mmapping the file"); + exit(EXIT_FAILURE); + } + file_size = fileInfo.st_size; + return buf; +} + +void deallocate_shared_buffer(char *buf) { + // Don't forget to free the mmapped memory + if (munmap(buf, file_size) == -1) + { + close(fd); + perror("Error un-mmapping the file"); + exit(EXIT_FAILURE); + } + + // Un-mmaping doesn't close the file, so we still need to do that. + close(fd); +} diff --git a/Part2-FlushReload/util.h b/Part2-FlushReload/util.h new file mode 100755 index 0000000..a3217f3 --- /dev/null +++ b/Part2-FlushReload/util.h @@ -0,0 +1,31 @@ + +// You may only use fgets() to pull input from stdin +// You may use any print function to stdout to print +// out chat messages +#include + +// You may use memory allocators and helper functions +// (e.g., rand()). You may not use system(). +#include + +#include +#include +#include + +#ifndef UTIL_H_ +#define UTIL_H_ + +#define SEC_RANGE 1024 +#define ALIGN 128 + +#define ADDR_PTR uint64_t +#define CYCLES uint32_t + +CYCLES measure_one_block_access_time(ADDR_PTR addr); + +void clflush(ADDR_PTR addr); + +char *allocate_shared_buffer(); +void deallocate_shared_buffer(char *buf); + +#endif diff --git a/Part2-FlushReload/victim b/Part2-FlushReload/victim new file mode 100755 index 0000000..737b9b7 Binary files /dev/null and b/Part2-FlushReload/victim differ diff --git a/Part3-PrimeProbe/.gitignore b/Part3-PrimeProbe/.gitignore new file mode 100644 index 0000000..5723c0a --- /dev/null +++ b/Part3-PrimeProbe/.gitignore @@ -0,0 +1,2 @@ +/*.o +/attacker diff --git a/Part3-CTF/Makefile b/Part3-PrimeProbe/Makefile similarity index 89% rename from Part3-CTF/Makefile rename to Part3-PrimeProbe/Makefile index 39e47ad..1f51279 100644 --- a/Part3-CTF/Makefile +++ b/Part3-PrimeProbe/Makefile @@ -23,6 +23,9 @@ run_victim-3: run_victim-4: taskset -c $(SENDER_CPU) ./victim-4 +run_victim-16: + taskset -c $(SENDER_CPU) ./victim-16 + run_attacker: attacker taskset -c $(RECEIVER_CPU) ./attacker diff --git a/Part3-CTF/attacker.c b/Part3-PrimeProbe/attacker.c similarity index 81% rename from Part3-CTF/attacker.c rename to Part3-PrimeProbe/attacker.c index 7679cea..f90d437 100644 --- a/Part3-CTF/attacker.c +++ b/Part3-PrimeProbe/attacker.c @@ -5,7 +5,7 @@ int main(int argc, char const *argv[]) { int flag = -1; - // Put your capture-the-flag code here + // [3.2] TODO: Put your capture-the-flag code here printf("Flag: %d\n", flag); return 0; diff --git a/Part3-CTF/util.c b/Part3-PrimeProbe/util.c similarity index 100% rename from Part3-CTF/util.c rename to Part3-PrimeProbe/util.c diff --git a/Part3-CTF/util.h b/Part3-PrimeProbe/util.h similarity index 100% rename from Part3-CTF/util.h rename to Part3-PrimeProbe/util.h diff --git a/Part3-PrimeProbe/victim-16 b/Part3-PrimeProbe/victim-16 new file mode 100755 index 0000000..e8f9310 Binary files /dev/null and b/Part3-PrimeProbe/victim-16 differ diff --git a/Part3-CTF/victim-2 b/Part3-PrimeProbe/victim-2 similarity index 100% rename from Part3-CTF/victim-2 rename to Part3-PrimeProbe/victim-2 diff --git a/Part3-CTF/victim-3 b/Part3-PrimeProbe/victim-3 similarity index 100% rename from Part3-CTF/victim-3 rename to Part3-PrimeProbe/victim-3 diff --git a/Part3-CTF/victim-4 b/Part3-PrimeProbe/victim-4 similarity index 100% rename from Part3-CTF/victim-4 rename to Part3-PrimeProbe/victim-4 diff --git a/README.md b/README.md index c368efa..2f20c53 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,6 @@ This repository contains all the starting code you will need for the lab. ## Starting the Lab -As stated on the lab handout, you must first change the `SENDER_CPU` and `RECEIVER_CPU` variables in the Makefile to your assigned CPUs. These will be emailed to you along with your lab machine password when the lab is released. **Double check that you have set these values correctly.** +As stated on the lab handout, you must first change the `SENDER_CPU` and `RECEIVER_CPU` variables in the `cpu.mk` to your assigned CPUs. **Double check that you have set these values correctly.** After completing these steps, you are now ready to start the lab. Good luck! diff --git a/report.md b/report.md new file mode 100644 index 0000000..422e468 --- /dev/null +++ b/report.md @@ -0,0 +1,38 @@ +## 1-1 + +**Fill in the blanks in the following table using the information you gathered about the cache configuration of the lab machine.** + +| Cache | Cache Line Size | Total Size | Associativity | Number of Sets | Raw Latency | +| ----- | --------------- | ---------- | ------------- | -------------- | ----------- | +| L1-D | 64 | | | | | +| L2 | | | | | | +| L3 | | | | | | + +## 1-3 + +**After completing your code, generate the histogram pdf file and include it in the lab report.** + + + +## 1-4 + +**Based on the generated histogram, report two thresholds, one to distinguish between L2 and L3 latency and the other to distinguish between L3 and DRAM latency.** + +L2-L3 threshold: + +L3-DRAM threshold: + +## 2-2 + +**If the victim want to read the kth byte of a file, where k is a secret, how can he/she avoid leaking the secret to the attacker?** + +## 3-1 + +**Given a 64-bit virtual address, fill in the table below.** + +| Page Size | 4KB | 2MB | +| ------------------------------------- | ------- | ------- | +| Page Offset Bits | | | +| Page Number Bits | | | +| L2 Set Index Bits | | | +| L2 Set Index Bits Fully Under Control | | | diff --git a/update.sh b/update.sh deleted file mode 100644 index c5fe63d..0000000 --- a/update.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/bash -# Updates repository to latest starter code -# -# Adapted from Oliver Beckstein's ASU-CompMethodsPhysics-PHY494 course 2016-2020 placed into the public domain - -# With GitHub template repositories one needs to use --allow-unrelated-histories -# at least once. https://help.github.com/en/github/creating-cloning-and-archiving-repositories/creating-a-repository-from-a-template - -progname="$0" -REMOTE_NAME="startercode" -REMOTE_URL="https://github.com/CSAIL-Arch-Sec/SHD-CacheAttackLab.git" - -# progname, from top dir -UPDATESH="./deploy/$(basename $progname)" - -CONTACT_MESSAGE="Contact the instructor and TA with a screen shot of ALL output from running $0." - -function die () { - local msg="$1" err=${2:-1} - echo "ERROR: ${msg}." - exit $err -} - -# ensure everything relative to top dir -topdir="$(git rev-parse --show-toplevel)" || die "Failed to get rootdir" -cd "${topdir}" || die "Failed to get to the git root dir ${rootdir}" - - -# first time -# 1. set remote repo -# 2. merge histories between student (template) and remote skeleton - -if ! git remote get-url ${REMOTE_NAME} >/dev/null 2>&1; then - echo "Adding remote repository '${REMOTE_NAME}'." - git remote add ${REMOTE_NAME} ${REMOTE_URL} - - echo "Merging histories for the first time..." - set -x - git pull --allow-unrelated-histories -s recursive -X theirs --no-edit ${REMOTE_NAME} main || \ - { git rev-list -1 MERGE_HEAD >/dev/null 2>&1 && git merge --abort ; \ - git remote rm ${REMOTE_NAME}; \ - die "Failed to merge histories. ${CONTACT_MESSAGE}" $?; } - - set +x -fi - -echo "updating repository... git pull from ${REMOTE_NAME}" -git pull --no-edit ${REMOTE_NAME} main || die "Failed to pull from ${REMOTE_NAME}. ${CONTACT_MESSAGE}"