Skip to content

Instantly share code, notes, and snippets.

@thomas-holmes
Last active October 4, 2019 21:21
Show Gist options
  • Save thomas-holmes/6d4808bcad43ecce32444ffeeca13ae6 to your computer and use it in GitHub Desktop.
Save thomas-holmes/6d4808bcad43ecce32444ffeeca13ae6 to your computer and use it in GitHub Desktop.

To reproduce this bug the file must be in an OverlayFS mount

Reproduced on:

  • linux-image-4.4.0-159-generic/xenial-updates,xenial-security,now 4.4.0-159.187 amd64
  • linux-image-4.4.0-165-generic/xenial-updates,xenial-security,now 4.4.0-165.193 amd64

Install packages libacl1-dev, build-essential, and gcc.

Included is a C program that reproduces the bug and two scripts. Run them in order.

  • make-overlay.sh: creates directories in /tmp and mounts /tmp/overlay as an overlay filesystem
  • test.sh: compiles the c program and executes it. additionally attempts to read the file and checks its permissions after the program exits.

Output:

ubuntu@:~/ctr$ ./make-overlay.sh
ubuntu@:~/ctr$ ./test.sh
st_mode is 100644
open failed: -1
cat: /tmp/overlay/animal: Permission denied
-rw-r--r-- 1 ubuntu ubuntu 0 Oct  4 19:40 /tmp/overlay/animal
#include <acl/libacl.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/acl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int main(void) {
int ret;
int fd = open("/tmp/overlay/animal", O_RDWR|O_CREAT|O_EXCL, 0000);
if (fd < 0) {
printf("open failed\n");
return 1;
}
acl_t acl = acl_from_mode(0644);
if (acl == NULL) {
printf("acl_from_mode failed\n");
return 1;
}
ret = acl_set_fd(fd, acl);
if (ret < 0) {
printf("acl_set_fd failed");
return 1;
}
// It works, apparently. But not really.
struct stat st;
if (fstat(fd, &st) < 0) {
printf("fstat failed\n");
return 1;
}
// reports 100644
printf("st_mode is %o\n", st.st_mode);
ret = close(fd);
if (ret < 0) {
printf("close failed\n");
return 1;
}
// fails to open
fd = open("/tmp/overlay/animal", O_RDONLY);
if (fd < 0) {
printf("open failed: %d\n", fd);
return 1;
}
}
#!/usr/bin/env bash
# setup directories for our overlay filesystem
mkdir /tmp/lower /tmp/upper /tmp/overlay /tmp/workdir
# mount the overlay filesystem
sudo mount -t overlay -o lowerdir=/tmp/lower,upperdir=/tmp/upper,workdir=/tmp/workdir none /tmp/overlay
#!/usr/bin/env bash
# compile the test program, run it, and try to inspect the files afterwards
gcc -Wl,--no-as-needed -lacl -o boom boom.c && rm -f /tmp/overlay/animal && ./boom; { cat /tmp/overlay/animal; ls -al /tmp/overlay/animal; }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment