containers/conmon

Anonymous pipe permission too restrictive on linux

afazekas opened this issue · 0 comments

We have an application which drops privileges and expects
the /dev/stderr and /dev/stdout is openable after that.

We are using crio (crc 2.20).

Ruining example:

root 24667 0.0 0.0 8308 2036 ? Ss 07:49 0:00 /usr/bin/conmon -b /run/containers/storage/overlay-containers/4005b749174d7e3df64537db1cf10916c0722156a4b8020f088bc27e26d72d5e/userdata -c 4005b749174d7e3df64537db1cf10916c0722156a4b8020f088bc27e26d72d5e --exit-dir /var/run/crio/exits -l /var/log/pods/openstack_cinder-api-6f74cd6657-gqr6f_b00842f0-b252-4e50-94a2-ca09786c45ea/cinder-api/357.log --log-level info -n k8s_cinder-api_cinder-api-6f74cd6657-gqr6f_openstack_b00842f0-b252-4e50-94a2-ca09786c45ea_357 -P /run/containers/storage/overlay-containers/4005b749174d7e3df64537db1cf10916c0722156a4b8020f088bc27e26d72d5e/userdata/conmon-pidfile -p /run/containers/storage/overlay-containers/4005b749174d7e3df64537db1cf10916c0722156a4b8020f088bc27e26d72d5e/userdata/pidfile --persist-dir /var/lib/containers/storage/overlay-containers/4005b749174d7e3df64537db1cf10916c0722156a4b8020f088bc27e26d72d5e/userdata -r /usr/bin/runc --runtime-arg --root=/run/runc --socket-dir-path /var/run/crio --syslog -u 4005b749174d7e3df64537db1cf10916c0722156a4b8020f088bc27e26d72d5e -s

Minified not working app:

#!/usr/bin/python

import os

uid = 1000

os.setuid(uid)
os.seteuid(uid)
f = open("/dev/stdout", "w")
f.write("bar")
f.close()

expected:

$ oc logs test
bar[zuul@host~]$

got:

oc logs test
Traceback (most recent call last):
File "/usr/bin/uidfork.py", line 9, in
f = open("/dev/stdout", "w")
^^^^^^^^^^^^^^^^^^^^^^^^
PermissionError: [Errno 13] Permission denied: '/dev/stdout'

The open become working in 2020:
#112

Not working around (2022):
32816bd

Simple fix:

diff -Naur conmon-c26648e58b57312ccb513015bacdf40936d6400dorig/src/conmon.c conmon-c26648e58b57312ccb513015bacdf40936d6400d/src/conmon.c
--- conmon-c26648e58b57312ccb513015bacdf40936d6400dorig/src/conmon.c	2023-06-07 09:31:47.354796067 +0200
+++ conmon-c26648e58b57312ccb513015bacdf40936d6400d/src/conmon.c	2023-06-07 09:37:26.787842327 +0200
@@ -36,6 +36,13 @@
 
 #define DEFAULT_UMASK 0022
 
+#ifdef __linux__
+/* Linux does not needs tty check*/
+#define ISATTY(x) true
+#else
+#define ISATTY(x) isatty(x) 
+#endif
+
 int main(int argc, char *argv[])
 {
 	setlocale(LC_ALL, "");
@@ -240,21 +247,21 @@
 				workerfd_stdin = dev_null_r;
 			if (dup2(workerfd_stdin, STDIN_FILENO) < 0)
 				_pexit("Failed to dup over stdin");
-			if (workerfd_stdin != dev_null_r && isatty(workerfd_stdin) && fchmod(STDIN_FILENO, 0777) < 0)
+			if (workerfd_stdin != dev_null_r && ISATTY(workerfd_stdin) && fchmod(STDIN_FILENO, 0777) < 0)
 				nwarn("Failed to chmod stdin");
 
 			if (workerfd_stdout < 0)
 				workerfd_stdout = dev_null_w;
 			if (dup2(workerfd_stdout, STDOUT_FILENO) < 0)
 				_pexit("Failed to dup over stdout");
-			if (workerfd_stdout != dev_null_w && isatty(workerfd_stdout) && fchmod(STDOUT_FILENO, 0777) < 0)
+			if (workerfd_stdout != dev_null_w && ISATTY(workerfd_stdout) && fchmod(STDOUT_FILENO, 0777) < 0)
 				nwarn("Failed to chmod stdout");
 
 			if (workerfd_stderr < 0)
 				workerfd_stderr = workerfd_stdout;
 			if (dup2(workerfd_stderr, STDERR_FILENO) < 0)
 				_pexit("Failed to dup over stderr");
-			if (workerfd_stderr != dev_null_w && isatty(workerfd_stderr) && fchmod(STDERR_FILENO, 0777) < 0)
+			if (workerfd_stderr != dev_null_w && ISATTY(workerfd_stderr) && fchmod(STDERR_FILENO, 0777) < 0)
 				nwarn("Failed to chmod stderr");
 		}
 		/* If LISTEN_PID env is set, we need to set the LISTEN_PID

Should I send pull request or there is a better way to handle this ?