Merge pull request #27634 from justincormack/user-cap-test

Test that non root user cannot use default capabilities
This commit is contained in:
Victor Vieux 2016-10-24 01:26:02 -07:00 committed by GitHub
commit 190a96131c
7 changed files with 245 additions and 1 deletions

View file

@ -6,4 +6,8 @@ WORKDIR /usr/src/
RUN gcc -g -Wall -static userns.c -o /usr/bin/userns-test \
&& gcc -g -Wall -static ns.c -o /usr/bin/ns-test \
&& gcc -g -Wall -static acct.c -o /usr/bin/acct-test
&& gcc -g -Wall -static acct.c -o /usr/bin/acct-test \
&& gcc -g -Wall -static setuid.c -o /usr/bin/setuid-test \
&& gcc -g -Wall -static setgid.c -o /usr/bin/setgid-test \
&& gcc -g -Wall -static socket.c -o /usr/bin/socket-test \
&& gcc -g -Wall -static raw.c -o /usr/bin/raw-test

View file

@ -0,0 +1,14 @@
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
int main() {
if (socket(PF_INET, SOCK_RAW, IPPROTO_UDP) == -1) {
perror("socket");
return 1;
}
return 0;
}

View file

@ -0,0 +1,11 @@
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main() {
if (setgid(1) == -1) {
perror("setgid");
return 1;
}
return 0;
}

View file

@ -0,0 +1,11 @@
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main() {
if (setuid(1) == -1) {
perror("setuid");
return 1;
}
return 0;
}

View file

@ -0,0 +1,30 @@
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main() {
int s;
struct sockaddr_in sin;
s = socket(AF_INET, SOCK_STREAM, 0);
if (s == -1) {
perror("socket");
return 1;
}
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(80);
if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
perror("bind");
return 1;
}
close(s);
return 0;
}

View file

@ -9,6 +9,10 @@ if [ "$DOCKER_ENGINE_GOOS" = "linux" ]; then
gcc -g -Wall -static contrib/syscall-test/userns.c -o "${tmpdir}/userns-test"
gcc -g -Wall -static contrib/syscall-test/ns.c -o "${tmpdir}/ns-test"
gcc -g -Wall -static contrib/syscall-test/acct.c -o "${tmpdir}/acct-test"
gcc -g -Wall -static contrib/syscall-test/setuid.c -o "${tmpdir}/setuid-test"
gcc -g -Wall -static contrib/syscall-test/setgid.c -o "${tmpdir}/setgid-test"
gcc -g -Wall -static contrib/syscall-test/socket.c -o "${tmpdir}/socket-test"
gcc -g -Wall -static contrib/syscall-test/raw.c -o "${tmpdir}/raw-test"
dockerfile="${tmpdir}/Dockerfile"
cat <<-EOF > "$dockerfile"

View file

@ -1138,6 +1138,176 @@ func (s *DockerSuite) TestRunNoNewPrivSetuid(c *check.C) {
}
}
func (s *DockerSuite) TestUserNoEffectiveCapabilitiesChown(c *check.C) {
testRequires(c, DaemonIsLinux)
// test that a root user has default capability CAP_CHOWN
runCmd := exec.Command(dockerBinary, "run", "busybox", "chown", "100", "/tmp")
_, _, err := runCommandWithOutput(runCmd)
c.Assert(err, check.IsNil)
// test that non root user does not have default capability CAP_CHOWN
runCmd = exec.Command(dockerBinary, "run", "--user", "1000:1000", "busybox", "chown", "100", "/tmp")
out, _, err := runCommandWithOutput(runCmd)
c.Assert(err, checker.NotNil, check.Commentf(out))
c.Assert(out, checker.Contains, "Operation not permitted")
// test that root user can drop default capability CAP_CHOWN
runCmd = exec.Command(dockerBinary, "run", "--cap-drop", "chown", "busybox", "chown", "100", "/tmp")
out, _, err = runCommandWithOutput(runCmd)
c.Assert(err, checker.NotNil, check.Commentf(out))
c.Assert(out, checker.Contains, "Operation not permitted")
}
func (s *DockerSuite) TestUserNoEffectiveCapabilitiesDacOverride(c *check.C) {
testRequires(c, DaemonIsLinux)
// test that a root user has default capability CAP_DAC_OVERRIDE
runCmd := exec.Command(dockerBinary, "run", "busybox", "sh", "-c", "echo test > /etc/passwd")
_, _, err := runCommandWithOutput(runCmd)
c.Assert(err, check.IsNil)
// test that non root user does not have default capability CAP_DAC_OVERRIDE
runCmd = exec.Command(dockerBinary, "run", "--user", "1000:1000", "busybox", "sh", "-c", "echo test > /etc/passwd")
out, _, err := runCommandWithOutput(runCmd)
c.Assert(err, checker.NotNil, check.Commentf(out))
c.Assert(out, checker.Contains, "Permission denied")
// TODO test that root user can drop default capability CAP_DAC_OVERRIDE
}
func (s *DockerSuite) TestUserNoEffectiveCapabilitiesFowner(c *check.C) {
testRequires(c, DaemonIsLinux)
// test that a root user has default capability CAP_FOWNER
runCmd := exec.Command(dockerBinary, "run", "busybox", "chmod", "777", "/etc/passwd")
_, _, err := runCommandWithOutput(runCmd)
c.Assert(err, check.IsNil)
// test that non root user does not have default capability CAP_FOWNER
runCmd = exec.Command(dockerBinary, "run", "--user", "1000:1000", "busybox", "chmod", "777", "/etc/passwd")
out, _, err := runCommandWithOutput(runCmd)
c.Assert(err, checker.NotNil, check.Commentf(out))
c.Assert(out, checker.Contains, "Operation not permitted")
// TODO test that root user can drop default capability CAP_FOWNER
}
// TODO CAP_KILL
func (s *DockerSuite) TestUserNoEffectiveCapabilitiesSetuid(c *check.C) {
testRequires(c, DaemonIsLinux)
// test that a root user has default capability CAP_SETUID
runCmd := exec.Command(dockerBinary, "run", "syscall-test", "setuid-test")
_, _, err := runCommandWithOutput(runCmd)
c.Assert(err, check.IsNil)
// test that non root user does not have default capability CAP_SETUID
runCmd = exec.Command(dockerBinary, "run", "--user", "1000:1000", "syscall-test", "setuid-test")
out, _, err := runCommandWithOutput(runCmd)
c.Assert(err, checker.NotNil, check.Commentf(out))
c.Assert(out, checker.Contains, "Operation not permitted")
// test that root user can drop default capability CAP_SETUID
runCmd = exec.Command(dockerBinary, "run", "--cap-drop", "setuid", "syscall-test", "setuid-test")
out, _, err = runCommandWithOutput(runCmd)
c.Assert(err, checker.NotNil, check.Commentf(out))
c.Assert(out, checker.Contains, "Operation not permitted")
}
func (s *DockerSuite) TestUserNoEffectiveCapabilitiesSetgid(c *check.C) {
testRequires(c, DaemonIsLinux)
// test that a root user has default capability CAP_SETGID
runCmd := exec.Command(dockerBinary, "run", "syscall-test", "setgid-test")
_, _, err := runCommandWithOutput(runCmd)
c.Assert(err, check.IsNil)
// test that non root user does not have default capability CAP_SETGID
runCmd = exec.Command(dockerBinary, "run", "--user", "1000:1000", "syscall-test", "setgid-test")
out, _, err := runCommandWithOutput(runCmd)
c.Assert(err, checker.NotNil, check.Commentf(out))
c.Assert(out, checker.Contains, "Operation not permitted")
// test that root user can drop default capability CAP_SETGID
runCmd = exec.Command(dockerBinary, "run", "--cap-drop", "setgid", "syscall-test", "setgid-test")
out, _, err = runCommandWithOutput(runCmd)
c.Assert(err, checker.NotNil, check.Commentf(out))
c.Assert(out, checker.Contains, "Operation not permitted")
}
// TODO CAP_SETPCAP
func (s *DockerSuite) TestUserNoEffectiveCapabilitiesNetBindService(c *check.C) {
testRequires(c, DaemonIsLinux)
// test that a root user has default capability CAP_NET_BIND_SERVICE
runCmd := exec.Command(dockerBinary, "run", "syscall-test", "socket-test")
_, _, err := runCommandWithOutput(runCmd)
c.Assert(err, check.IsNil)
// test that non root user does not have default capability CAP_NET_BIND_SERVICE
runCmd = exec.Command(dockerBinary, "run", "--user", "1000:1000", "syscall-test", "socket-test")
out, _, err := runCommandWithOutput(runCmd)
c.Assert(err, checker.NotNil, check.Commentf(out))
c.Assert(out, checker.Contains, "Permission denied")
// test that root user can drop default capability CAP_NET_BIND_SERVICE
runCmd = exec.Command(dockerBinary, "run", "--cap-drop", "net_bind_service", "syscall-test", "socket-test")
out, _, err = runCommandWithOutput(runCmd)
c.Assert(err, checker.NotNil, check.Commentf(out))
c.Assert(out, checker.Contains, "Permission denied")
}
func (s *DockerSuite) TestUserNoEffectiveCapabilitiesNetRaw(c *check.C) {
testRequires(c, DaemonIsLinux)
// test that a root user has default capability CAP_NET_RAW
runCmd := exec.Command(dockerBinary, "run", "syscall-test", "raw-test")
_, _, err := runCommandWithOutput(runCmd)
c.Assert(err, check.IsNil)
// test that non root user does not have default capability CAP_NET_RAW
runCmd = exec.Command(dockerBinary, "run", "--user", "1000:1000", "syscall-test", "raw-test")
out, _, err := runCommandWithOutput(runCmd)
c.Assert(err, checker.NotNil, check.Commentf(out))
c.Assert(out, checker.Contains, "Operation not permitted")
// test non root can drop default capability CAP_NET_RAW
runCmd = exec.Command(dockerBinary, "run", "--cap-drop", "net_raw", "syscall-test", "raw-test")
out, _, err = runCommandWithOutput(runCmd)
c.Assert(err, checker.NotNil, check.Commentf(out))
c.Assert(out, checker.Contains, "Operation not permitted")
}
func (s *DockerSuite) TestUserNoEffectiveCapabilitiesChroot(c *check.C) {
testRequires(c, DaemonIsLinux)
// test that a root user has default capability CAP_SYS_CHROOT
runCmd := exec.Command(dockerBinary, "run", "busybox", "chroot", "/", "/bin/true")
_, _, err := runCommandWithOutput(runCmd)
c.Assert(err, check.IsNil)
// test that non root user does not have default capability CAP_SYS_CHROOT
runCmd = exec.Command(dockerBinary, "run", "--user", "1000:1000", "busybox", "chroot", "/", "/bin/true")
out, _, err := runCommandWithOutput(runCmd)
c.Assert(err, checker.NotNil, check.Commentf(out))
c.Assert(out, checker.Contains, "Operation not permitted")
// test that root user can drop default capability CAP_SYS_CHROOT
runCmd = exec.Command(dockerBinary, "run", "--cap-drop", "sys_chroot", "busybox", "chroot", "/", "/bin/true")
out, _, err = runCommandWithOutput(runCmd)
c.Assert(err, checker.NotNil, check.Commentf(out))
c.Assert(out, checker.Contains, "Operation not permitted")
}
func (s *DockerSuite) TestUserNoEffectiveCapabilitiesMknod(c *check.C) {
testRequires(c, DaemonIsLinux)
// test that a root user has default capability CAP_MKNOD
runCmd := exec.Command(dockerBinary, "run", "busybox", "mknod", "/tmp/node", "b", "1", "2")
_, _, err := runCommandWithOutput(runCmd)
c.Assert(err, check.IsNil)
// test that non root user does not have default capability CAP_MKNOD
runCmd = exec.Command(dockerBinary, "run", "--user", "1000:1000", "busybox", "mknod", "/tmp/node", "b", "1", "2")
out, _, err := runCommandWithOutput(runCmd)
c.Assert(err, checker.NotNil, check.Commentf(out))
c.Assert(out, checker.Contains, "Operation not permitted")
// test that root user can drop default capability CAP_MKNOD
runCmd = exec.Command(dockerBinary, "run", "--cap-drop", "mknod", "busybox", "mknod", "/tmp/node", "b", "1", "2")
out, _, err = runCommandWithOutput(runCmd)
c.Assert(err, checker.NotNil, check.Commentf(out))
c.Assert(out, checker.Contains, "Operation not permitted")
}
// TODO CAP_AUDIT_WRITE
// TODO CAP_SETFCAP
func (s *DockerSuite) TestRunApparmorProcDirectory(c *check.C) {
testRequires(c, SameHostDaemon, Apparmor)