systemd: Intermediate --chroot fix with the new sd_notify() implementation
PATCH 1/1 systemd: Intermediate --chroot fix with the new sd_notify() implementation
Commit c5931897ae8d663e7e introduced support for talking directly to the systemd service manager about the situation for the OpenVPN tunnel. This approach makes a lot of sense and is mostly the proper way to do it. But it was discovered that it breaks OpenVPN configurations using --chroot.
The reason sd_notify() calls fails when using chroot() is that sd_notify() expects to have access to a file as declared in the $NOTIFY_SOCKET environment variable. It is the main systemd instance which is responsible to provide both the environment variable as well as the socket file sd_nodify() should use. When --chroot comes into play, the $NOTIFY_SOCKET file will not be available for OpenVPN any more.
As things are getting close to the 2.4_rc2 release we will not dare to bring a too invasive fix. As well we need some time to discuss an approrpriate solution. So this intermediate fix will only provide a "successful start" message to the systemd service manager right before chroot() happens. This will at least resolve the issue in a safe and non-intrusive way.
--- src/openvpn/init.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-)
src/openvpn/init.c +21 -1
@@ -967,7 +967,27 @@ do_uid_gid_chroot (struct context *c, bool no_delay)if (c->options.chroot_dir) {if (no_delay) -platform_chroot (c->options.chroot_dir); + { +#ifdef ENABLE_SYSTEMD +/* If OpenVPN is started by systemd, the OpenVPN process needs +* to provide a preliminary status report to systemd. This is +* needed as $NOTIFY_SOCKET will not be available inside the +* chroot, which sd_notify()/sd_notifyf() depends on. +* +* This approach is the simplest and the most non-intrusive +* solution right before the 2.4_rc2 release. +* +* TODO: Consider altnernative solutions - bind mount? +* systemd does not grok OpenVPN configuration files, thus cannot +* have a sane way to know if OpenVPN will chroot or not and to +* which subdirectory it will chroot into. +*/ +sd_notifyf (0 ,"READY=1\n" +"STATUS=Entering chroot, most of the init completed successfully\n" +"MAINPID=%lu" , (unsigned long )getpid ()); +#endif +platform_chroot (c->options.chroot_dir); + }else if (c->first_time)msg (M_INFO ,"NOTE: chroot %s" , why_not); }
Signature · 1 line
1.8.3.1
David Sommerseth <[email protected]...> on Wed, 2016/12/07 03:51:
Quoted 57 lines
Commit
c5931897ae8d663e7eintroduced support for talking directly to the systemd service manager about the situation for the OpenVPN tunnel. This approach makes a lot of sense and is mostly the proper way to do it. But it was discovered that it breaks OpenVPN configurations using --chroot.The reason
sd_notify()calls fails when usingchroot()is thatsd_notify()expects to have access to a file as declared in the $NOTIFY_SOCKET environment variable. It is the main systemd instance which is responsible to provide both the environment variable as well as the socket filesd_nodify()should use. When --chroot comes into play, the $NOTIFY_SOCKET file will not be available for OpenVPN any more.As things are getting close to the 2.4_rc2 release we will not dare to bring a too invasive fix. As well we need some time to discuss an approrpriate solution. So this intermediate fix will only provide a "successful start" message to the systemd service manager right before
chroot()happens. This will at least resolve the issue in a safe and non-intrusive way.Signed-off-by David Sommerseth <[email protected]...>--- src/openvpn/init.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-)src/openvpn/init.c +3
-1@@ -967,7 +967,27 @@ do_uid_gid_chroot (struct context *c, bool no_delay)if (c->options.chroot_dir) {if (no_delay) -platform_chroot (c->options.chroot_dir); + { +#ifdef ENABLE_SYSTEMD +/* If OpenVPN is started by systemd, the OpenVPN process needs
+ * to provide a preliminary status report to systemd. This
issrc/openvpn/init.c +8
-0+* needed as $NOTIFY_SOCKET will not be available inside the +* chroot, which sd_notify()/sd_notifyf() depends on. +* +* This approach is the simplest and the most non-intrusive +* solution right before the 2.4_rc2 release. +* +* TODO: Consider altnernative solutions - bind mount? +* systemd does not grok OpenVPN configuration files, thus cannot
+ * have a sane way to know if OpenVPN will chroot or not and
tosrc/openvpn/init.c +4
-0+* which subdirectory it will chroot into. +*/ +sd_notifyf (0 ,"READY=1\n" + "STATUS=Entering chroot, most of the init completedsuccessfully\n"
src/openvpn/init.c do_uid_gid_chroot (struct context *c, bool no_delay) · line 993
Quoted 7 lines
src/openvpn/init.c +4
-0+ "MAINPID=%lu", (unsigned long) getpid()); +#endif +platform_chroot (c->options.chroot_dir); + }else if (c->first_time)msg (M_INFO ,"NOTE: chroot %s" , why_not); }
Looks good to me, so: ACK
In long term we should think about a proper solution. Notification socket is /run/systemd/notify, so we would have to make that available from within the chroot.
BTW, feel free to CC me on systemd related topics.
Signature · 3 lines
main(a){char*c=/* Schoene Gruesse */"B?IJj;MEH"
"CX:;",b;for(a/* Best regards my address: */=0;b=c[a++];)
putchar(b-1/(/* Chris cc -ox -xc - && ./x */b/42*2-3)*42);}Christian Hesse <[email protected]...> on Fri, 2016/12/09 18:37:
Quoted 69 lines
David Sommerseth <[email protected]...> on Wed, 2016/12/07 03:51:
Quoted 58 lines
Commit
c5931897ae8d663e7eintroduced support for talking directly to the systemd service manager about the situation for the OpenVPN tunnel. This approach makes a lot of sense and is mostly the proper way to do it. But it was discovered that it breaks OpenVPN configurations using --chroot.The reason
sd_notify()calls fails when usingchroot()is thatsd_notify()expects to have access to a file as declared in the $NOTIFY_SOCKET environment variable. It is the main systemd instance which is responsible to provide both the environment variable as well as the socket filesd_nodify()should use. When --chroot comes into play, the $NOTIFY_SOCKET file will not be available for OpenVPN any more.As things are getting close to the 2.4_rc2 release we will not dare to bring a too invasive fix. As well we need some time to discuss an approrpriate solution. So this intermediate fix will only provide a "successful start" message to the systemd service manager right before
chroot()happens. This will at least resolve the issue in a safe and non-intrusive way.Signed-off-by David Sommerseth <[email protected]...>--- src/openvpn/init.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-)src/openvpn/init.c +3
-1@@ -967,7 +967,27 @@ do_uid_gid_chroot (struct context *c, bool no_delay)if (c->options.chroot_dir) {if (no_delay) -platform_chroot (c->options.chroot_dir); + { +#ifdef ENABLE_SYSTEMD +/* If OpenVPN is started by systemd, the OpenVPN process needs
+ * to provide a preliminary status report to systemd. This
is
+ * needed as $NOTIFY_SOCKET will not be available inside
thesrc/openvpn/init.c +7
-0+* chroot, which sd_notify()/sd_notifyf() depends on. +* +* This approach is the simplest and the most non-intrusive +* solution right before the 2.4_rc2 release. +* +* TODO: Consider altnernative solutions - bind mount? +* systemd does not grok OpenVPN configuration files, thus cannot
+ * have a sane way to know if OpenVPN will chroot or not
and tosrc/openvpn/init.c +4
-0+* which subdirectory it will chroot into. +*/ +sd_notifyf (0 ,"READY=1\n" + "STATUS=Entering chroot, most of the init completedsuccessfully\n"
src/openvpn/init.c do_uid_gid_chroot (struct context *c, bool no_delay) · line 993
Quoted 7 lines
src/openvpn/init.c +4
-0+ "MAINPID=%lu", (unsigned long) getpid()); +#endif +platform_chroot (c->options.chroot_dir); + }else if (c->first_time)msg (M_INFO ,"NOTE: chroot %s" , why_not); }Looks good to me, so: ACK
Quoted 3 lines
In long term we should think about a proper solution. Notification socket is
/run/systemd/notify, so we would have to make that available from within the chroot.
BTW, systemd used to use abstract sockets for notifications, which worked with processes that chroot themselves. This was changed [0] in favor to PrivateNetwork setting. Private network (in terms of systemd) is nothing we can make use of, though. Obviously... :-p
Does it make sense to deny to chroot when running from systemd and instead add some more security features to the systemd unit? Things like ProtectSystem=strict, ProtectHome=true and friends. See systemd.exec(5) [1] for details.
[0]
https://github.com/systemd/systemd/commit/7181dbdb2e3112858d62bdaea4f0ad2ed685ccba
[1] https://www.freedesktop.org/software/systemd/man/systemd.exec.html
Signature · 3 lines
main(a){char*c=/* Schoene Gruesse */"B?IJj;MEH"
"CX:;",b;for(a/* Best regards my address: */=0;b=c[a++];)
putchar(b-1/(/* Chris cc -ox -xc - && ./x */b/42*2-3)*42);}Quoted 69 lines · Christian Hesse
Christian Hesse <[email protected]...> on Fri, 2016/12/09 18:37:
Quoted 68 lines
David Sommerseth <[email protected]...> on Wed, 2016/12/07 03:51:
Quoted 58 lines
Commit
c5931897ae8d663e7eintroduced support for talking directly to the systemd service manager about the situation for the OpenVPN tunnel. This approach makes a lot of sense and is mostly the proper way to do it. But it was discovered that it breaks OpenVPN configurations using --chroot.The reason
sd_notify()calls fails when usingchroot()is thatsd_notify()expects to have access to a file as declared in the $NOTIFY_SOCKET environment variable. It is the main systemd instance which is responsible to provide both the environment variable as well as the socket filesd_nodify()should use. When --chroot comes into play, the $NOTIFY_SOCKET file will not be available for OpenVPN any more.As things are getting close to the 2.4_rc2 release we will not dare to bring a too invasive fix. As well we need some time to discuss an approrpriate solution. So this intermediate fix will only provide a "successful start" message to the systemd service manager right before
chroot()happens. This will at least resolve the issue in a safe and non-intrusive way.Signed-off-by David Sommerseth <[email protected]...>--- src/openvpn/init.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-)src/openvpn/init.c +3
-1@@ -967,7 +967,27 @@ do_uid_gid_chroot (struct context *c, bool no_delay)if (c->options.chroot_dir) {if (no_delay) -platform_chroot (c->options.chroot_dir); + { +#ifdef ENABLE_SYSTEMD +/* If OpenVPN is started by systemd, the OpenVPN process needs
+ * to provide a preliminary status report to systemd. This
is
+ * needed as $NOTIFY_SOCKET will not be available inside
thesrc/openvpn/init.c +7
-0+* chroot, which sd_notify()/sd_notifyf() depends on. +* +* This approach is the simplest and the most non-intrusive +* solution right before the 2.4_rc2 release. +* +* TODO: Consider altnernative solutions - bind mount? +* systemd does not grok OpenVPN configuration files, thus cannot
+ * have a sane way to know if OpenVPN will chroot or not
and tosrc/openvpn/init.c +4
-0+* which subdirectory it will chroot into. +*/ +sd_notifyf (0 ,"READY=1\n" + "STATUS=Entering chroot, most of the init completedsuccessfully\n"
src/openvpn/init.c do_uid_gid_chroot (struct context *c, bool no_delay) · line 993
Quoted 7 lines
src/openvpn/init.c +4
-0+ "MAINPID=%lu", (unsigned long) getpid()); +#endif +platform_chroot (c->options.chroot_dir); + }else if (c->first_time)msg (M_INFO ,"NOTE: chroot %s" , why_not); }Looks good to me, so: ACK
Thanks!
Quoted 8 lines
Quoted 3 lines
In long term we should think about a proper solution. Notification socket is
/run/systemd/notify, so we would have to make that available from within the chroot.BTW, systemd used to use abstract sockets for notifications, which worked with processes that chroot themselves. This was changed [0] in favor to PrivateNetwork setting. Private network (in terms of systemd) is nothing we can make use of, though. Obviously... :-p
:)
Quoted 4 lines
Does it make sense to deny to chroot when running from systemd and instead add some more security features to the systemd unit? Things like ProtectSystem=strict, ProtectHome=true and friends. See
systemd.exec(5)[1] for details.
Yes, I think this can make sense. I would also like to see more where things are headed in regards to namespaces (or app-container, if you want). If we can also isolate the openvpn process from as much as possible from the rest of the system (and find a solution for
$HOME/.cert). But still that does provide some other challenges,
though - like: What to do with script hooks and --plugin files? And especially other dependencies of shells/interpretors and shared objects they may depend on.
Perhaps a discussion we could open up with the systemd team?
Signature · 4 lines
kind regards, David Sommerseth OpenVPN Technologies, Inc
PATCH 1/1 bind mount systemd notification socket into chroot
In reply to Christian HesseFrom: Christian Hesse <[email protected]...>
sd_notify() uses a socket to communicate with systemd. Communication fails if the socket is not available within the chroot. So bind mount the socket into the chroot when startet from systemd.
Unsharing namespace and mounting requires extra capability CAP_SYS_ADMIN.
--- distro/systemd/[email protected]... | 2 +- distro/systemd/[email protected]... | 2 +- src/openvpn/init.c | 37 +++++++++++++++++++--------------- 3 files changed, 23 insertions(+), 18 deletions(-)
distro/systemd/[email protected]... +1 -1
@@ -13,7 +13,7 @@ RuntimeDirectory=openvpn-client RuntimeDirectoryMode=0710 WorkingDirectory=/etc/openvpn/client ExecStart=/usr/sbin/openvpn --suppress-timestamps --nobind --config %i.conf -CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_RAW CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_DAC_OVERRIDE +CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_RAW CAP_SETGID CAP_SETUID CAP_SYS_ADMIN CAP_SYS_CHROOT CAP_DAC_OVERRIDE LimitNPROC=10 DeviceAllow=/dev/null rw DeviceAllow=/dev/net/tun rw
distro/systemd/[email protected]... +1 -1
@@ -13,7 +13,7 @@ RuntimeDirectory=openvpn-server RuntimeDirectoryMode=0710 WorkingDirectory=/etc/openvpn/server ExecStart=/usr/sbin/openvpn --status %t/openvpn-server/status-%i.log --status-version 2 --suppress-timestamps --config %i.conf -CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_DAC_OVERRIDE +CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SETGID CAP_SETUID CAP_SYS_ADMIN CAP_SYS_CHROOT CAP_DAC_OVERRIDE LimitNPROC=10 DeviceAllow=/dev/null rw DeviceAllow=/dev/net/tun rw
src/openvpn/init.c +21 -16
@@ -31,6 +31,9 @@#include "syshead.h" #ifdef ENABLE_SYSTEMD +#include <string.h> +#include <sched.h> +#include <sys/mount.h> #include <systemd/sd-daemon.h> #endif
@@ -969,22 +972,24 @@ do_uid_gid_chroot (struct context *c, bool no_delay)if (no_delay) {#ifdef ENABLE_SYSTEMD -/* If OpenVPN is started by systemd, the OpenVPN process needs -* to provide a preliminary status report to systemd. This is -* needed as $NOTIFY_SOCKET will not be available inside the -* chroot, which sd_notify()/sd_notifyf() depends on. -* -* This approach is the simplest and the most non-intrusive -* solution right before the 2.4_rc2 release. -* -* TODO: Consider altnernative solutions - bind mount? -* systemd does not grok OpenVPN configuration files, thus cannot -* have a sane way to know if OpenVPN will chroot or not and to -* which subdirectory it will chroot into. -*/ -sd_notifyf (0 ,"READY=1\n" -"STATUS=Entering chroot, most of the init completed successfully\n" -"MAINPID=%lu" , (unsigned long )getpid ()); +int fd; +char * chroot_notify =NULL ; + +if (sd_notify (0 ,"READY=0" ) >0 ) + { +asprintf (&chroot_notify,"%s/notify" , c->options.chroot_dir); + +if (unshare (CLONE_NEWNS ) !=0 ) +msg (M_ERR ,"unshare failed" ); +if ((fd =open (chroot_notify,O_WRONLY |O_CREAT |O_TRUNC ,0644 )) <0 ) +msg (M_ERR ,"touch failed" ); +close (fd); +if (mount (getenv ("NOTIFY_SOCKET" ), chroot_notify,NULL ,MS_BIND ,NULL ) !=0 ) +msg (M_ERR ,"bind mounting notification socket failed" ); + +setenv ("NOTIFY_SOCKET" ,"/notify" ,1 ); +free (chroot_notify); + }#endif platform_chroot (c->options.chroot_dir); }
Signature · 1 line
2.10.2
Re: [Openvpn-devel] [PATCH 1/1] bind mount systemd notification socket into chroot
Quoted 7 lines · Christian Hesse
From: Christian Hesse <[email protected]...>
sd_notify()uses a socket to communicate with systemd. Communication fails if the socket is not available within the chroot. So bind mount the socket into the chroot when startet from systemd.Unsharing namespace and mounting requires extra capability
CAP_SYS_ADMIN.
I will pick up this one after 2.4.0 has been released. This is a very promising approach. However, I'm not too happy about CAP_SYS_ADMIN though, that grants quite some privileges. Can we look at dropping this capability once we know we won't need it any more? Perhaps when we send READY=1?
src/openvpn/init.c do_uid_gid_chroot (struct context *c, bool no_delay) · line 980
Quoted 5 lines
src/openvpn/init.c +5
-0+char * chroot_notify =NULL ; + +if (sd_notify (0 ,"READY=0" ) >0 ) + { +asprintf (&chroot_notify,"%s/notify" , c->options.chroot_dir);
Here we should use the buffer/string functions, based on the gc_arena implementation. Unfortunately we do not have a direct equivalent to asprintf(). A starting point would be to for example look at the string handling in print_sockaddr_ex() [socket.c:2386] or x_msg_va() [error.c:251] ... there might be better examples too, I'm just not able to remember them now :) .... buffer.[ch] keeps most of these functions.
The reason for this is basically to use the same well tested infrastructure. And with gc_arena, only a single gc_free() is required, regardless of how many buffers you allocate to that arena.
Signature · 4 lines
kind regards, David Sommerseth OpenVPN Technologies, Inc
Re: [Openvpn-devel] [PATCH 1/1] bind mount systemd notification socket into chroot
David Sommerseth <[email protected]...> on Sat, 2016/12/10 01:03:
Quoted 7 lines · Christian Hesse
Quoted 6 lines
From: Christian Hesse <[email protected]...>
sd_notify()uses a socket to communicate with systemd. Communication fails if the socket is not available within the chroot. So bind mount the socket into the chroot when startet from systemd.
Quoted 8 lines
Quoted 2 lines
Unsharing namespace and mounting requires extra capability
CAP_SYS_ADMIN.I will pick up this one after 2.4.0 has been released. This is a very promising approach. However, I'm not too happy about
CAP_SYS_ADMINthough, that grants quite some privileges. Can we look at dropping this capability once we know we won't need it any more? Perhaps when we send READY=1?
Never tried to drop capabilities... Have to look into that. We do no longer need CAP_SYS_ADMIN after the bind mount. (Or not at all without chrooting.)
Quoted 14 lines
Quoted 6 lines
src/openvpn/init.c +5
-0+char * chroot_notify =NULL ; + +if (sd_notify (0 ,"READY=0" ) >0 ) + { + asprintf(&chroot_notify, "%s/notify",
c->options.chroot_dir);Here we should use the buffer/string functions, based on the
gc_arenaimplementation. Unfortunately we do not have a direct equivalent toasprintf(). A starting point would be to for example look at the string handling inprint_sockaddr_ex()[socket.c:2386] orx_msg_va()[error.c:251] ... there might be better examples too, I'm just not able to remember them now :) .... buffer.[ch] keeps most of these functions.
Quoted 3 lines
The reason for this is basically to use the same well tested infrastructure. And with
gc_arena, only a singlegc_free()is required, regardless of how many buffers you allocate to that arena.
I do not like this myself. The patch is just a proof of concept... So this should be polished before committing. ;)
Thanks for the hints, I will have a look.
Signature · 3 lines
main(a){char*c=/* Schoene Gruesse */"B?IJj;MEH"
"CX:;",b;for(a/* Best regards my address: */=0;b=c[a++];)
putchar(b-1/(/* Chris cc -ox -xc - && ./x */b/42*2-3)*42);}Re: [Openvpn-devel] [PATCH 1/1] bind mount systemd notification socket into chroot
Quoted 17 lines · Christian Hesse
David Sommerseth <[email protected]...> on Sat, 2016/12/10 01:03:
Quoted 7 lines · Christian Hesse
Quoted 6 lines
From: Christian Hesse <[email protected]...>
sd_notify()uses a socket to communicate with systemd. Communication fails if the socket is not available within the chroot. So bind mount the socket into the chroot when startet from systemd.Quoted 8 lines
Quoted 2 lines
Unsharing namespace and mounting requires extra capability
CAP_SYS_ADMIN.I will pick up this one after 2.4.0 has been released. This is a very promising approach. However, I'm not too happy about
CAP_SYS_ADMINthough, that grants quite some privileges. Can we look at dropping this capability once we know we won't need it any more? Perhaps when we send READY=1?
Quoted 3 lines
Never tried to drop capabilities... Have to look into that. We do no longer need
CAP_SYS_ADMINafter the bind mount. (Or not at all without chrooting.)
Sounds reasonable. Since we need to take CAP_SYS_ADMIN out of the unit file regardless, we need to drop the CAP_SYS_ADMIN capability inside OpenVPN anyhow. Just need to figure out the best place for it.
As a pointer for managing capabilities, have a look at the capsetp(3) man page.
Quoted 14 lines
Quoted 14 lines
Quoted 6 lines
src/openvpn/init.c +5
-0+char * chroot_notify =NULL ; + +if (sd_notify (0 ,"READY=0" ) >0 ) + { + asprintf(&chroot_notify, "%s/notify",
c->options.chroot_dir);Here we should use the buffer/string functions, based on the
gc_arenaimplementation. Unfortunately we do not have a direct equivalent toasprintf(). A starting point would be to for example look at the string handling inprint_sockaddr_ex()[socket.c:2386] orx_msg_va()[error.c:251] ... there might be better examples too, I'm just not able to remember them now :) .... buffer.[ch] keeps most of these functions.
Quoted 8 lines
Quoted 3 lines
The reason for this is basically to use the same well tested infrastructure. And with
gc_arena, only a singlegc_free()is required, regardless of how many buffers you allocate to that arena.I do not like this myself. The patch is just a proof of concept... So this should be polished before committing. ;)
Thanks for the hints, I will have a look.
It's a great PoC! And good to see that we might find a solution for this. Will look forward to dig deeper into this in the coming weeks too.
Signature · 4 lines
kind regards, David Sommerseth OpenVPN Technologies, Inc
Re: [Openvpn-devel] [PATCH 1/1] bind mount systemd notification socket into chroot
In reply to Christian HesseHi,
Quoted 5 lines · Christian Hesse
src/openvpn/init.c +5
-0+int fd; +char * chroot_notify =NULL ; + +if (sd_notify (0 ,"READY=0" ) >0 ) + {
src/openvpn/init.c do_uid_gid_chroot (struct context *c, bool no_delay) · line 989
Quoted 10 lines
src/openvpn/init.c +10
-0+asprintf (&chroot_notify,"%s/notify" , c->options.chroot_dir); + +if (unshare (CLONE_NEWNS ) !=0 ) +msg (M_ERR ,"unshare failed" ); +if ((fd =open (chroot_notify,O_WRONLY |O_CREAT |O_TRUNC ,0644 )) <0 ) +msg (M_ERR ,"touch failed" ); +close (fd); +if (mount (getenv ("NOTIFY_SOCKET" ), chroot_notify,NULL ,MS_BIND ,NULL ) !=0 ) +msg (M_ERR ,"bind mounting notification socket failed" ); +
This is WAY over the top of what should go into OpenVPN code. Really.
NAK on approach, NAK on code.
Is there a way make sd_notify() behave like syslog()? That is, you call something like "openlog()" which will acquire the necessary file descriptor and then you can afterwards chroot() to your heart's content and do not need access to the actual socket file anymore (because openlog() will keep it around for syslog() to use).
If sd_notify() cannot be taught to do that, either do what David proposed (disable chroot if running under systemd), or at least move that code out of init.c into something like platform.c.
gert
Signature · 4 lines
USENET is *not* the non-clickable part of WWW!
//www.muc.de/~gert/
Gert Doering - Munich, Germany [email protected]...
fax: +49-89-35655025 [email protected]...Re: [Openvpn-devel] [PATCH 1/1] bind mount systemd notification socket into chroot
Quoted 21 lines · Gert Doering
Hi,
Quoted 5 lines · Christian Hesse
src/openvpn/init.c +5
-0+int fd; +char * chroot_notify =NULL ; + +if (sd_notify (0 ,"READY=0" ) >0 ) + {src/openvpn/init.c do_uid_gid_chroot (struct context *c, bool no_delay) · line 989
Quoted 10 lines
src/openvpn/init.c +10
-0+asprintf (&chroot_notify,"%s/notify" , c->options.chroot_dir); + +if (unshare (CLONE_NEWNS ) !=0 ) +msg (M_ERR ,"unshare failed" ); +if ((fd =open (chroot_notify,O_WRONLY |O_CREAT |O_TRUNC ,0644 )) <0 ) +msg (M_ERR ,"touch failed" ); +close (fd); +if (mount (getenv ("NOTIFY_SOCKET" ), chroot_notify,NULL ,MS_BIND ,NULL ) !=0 ) +msg (M_ERR ,"bind mounting notification socket failed" ); +This is WAY over the top of what should go into OpenVPN code. Really.
Quoted 8 lines
NAK on approach, NAK on code.
Is there a way make
sd_notify()behave likesyslog()? That is, you call something like "openlog()" which will acquire the necessary file descriptor and then you can afterwardschroot()to your heart's content and do not need access to the actual socket file anymore (becauseopenlog()will keep it around forsyslog()to use).
First of all, bind mounts are fairly common in Linux these days - especially when you start to try to chroot/containerize (including docker)/"jail" and otherwise isolate applications. Chroots in general are considered a bit too easy to escape from, unless privileges are dropped at the right point. Namespaces and other container techniques are often somewhat better, but still does not yet provide the full isolation many expects. In this context bind mounts are often considered simpler and to some degree safer than a full mount of /dev, /proc, /sys, /run and so on.
Unfortunately, there exists no "openlog()" equivalent to my knowledge for sd_notify() and other functions depending on the /run/systemd directory. But it's a good idea, and in fact such a "prepare for chroot" in libsystemd could probably do such a bind mount for the caller. I have a good contact with one of the upstream systemd developers and will discuss this with him ... so with time, we might have something better.
Well, there is one feature systemd guys might throw at us instantly when we open this topic ... PrivateNetwork=true in the unit file. But that is useless for OpenVPN as then we will only have access to the lo network device, all other network devices are unavailable.
Quoted 3 lines
If
sd_notify()cannot be taught to do that, either do what David proposed (disable chroot if running under systemd), or at least move that code out ofinit.cinto something likeplatform.c.
That's a fair argument. As long as thelibsystemd shipped in RHEL7 does not, to our knowledge, carry such a feature which we need; implementing this functionality inside platform.c is reasonable.
What I am wondering then is if we should implement platform_chroot() which is called from init.c. Where it will just call chroot() on non-systemd and non-Windows systems. When systemd is enabled and detected detected it will prepare the bind mount, drop capabilities and then call chroot().
Is that a reasonable approach? Or would you prefer to have just the bind mount stuff isolated into platform.c?
Signature · 4 lines
kind regards, David Sommerseth OpenVPN Technologies, Inc
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Your patch has been applied to the master branch
commit 65140a3acfa42e5d42cdfcf8108f00a62d5767ff
Author: David Sommerseth Date: Wed Dec 7 03:51:52 2016 +0100
systemd: Intermediate --chroot fix with the new sd_notify() implementation
Signed-off-by: David Sommerseth <[email protected]...>
Acked-by: Christian Hesse <[email protected]...>
Message-Id: <[email protected]...>
URL: https://www.mail-archive.com/[email protected]/msg13416.html- --
kind regards,
David Sommerseth
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.22 (GNU/Linux)
iQIcBAEBAgAGBQJYSyTlAAoJEIbPlEyWcf3y/sMQAMaJhmd4WJjjr7am+6SqMyWg pk7J4FzysRu8Dm/czDEULAriDO6YDMrVN/HNO3z/tLxUKnwvP1Qq9RbzM1HwDHbH 3vuVFu/Id4GGwiVqu35LsOq0dVwLra188L709AgTqepCXCuajUxSDtl8lcTCL2vN gDTL0FiYQSTl/jAlMKAeFg8W8C5pFDPOUumBgcYNdqqwW7FUPsl5JYqZup9bqgPO cuY5kSx8GUe7En1EPSbGIdX/cVwkHDtxs9Caqpr1Qb0d8iinchDCaz8YrYDjvpkG j1NE32lNbWLpeiXP2hLN9YIg+V7TSuT1jCyUwKJUEt/y0dZxdlpfeyS52WAGVTZY BaRmnzdGHmdYbSSv8ft1qKh6NI/3sRfmSzd2+eb9dTC2FsUUSoprU0yAISYR+dew Jvp8jeE/F4xUGKp6ierMkzvmqtudQRrq3hkmtbpS1CaM2Pf+uugQ7Z3s7rk+GRwb 2E0YpzKQNheeTsbInQWJQoXLZx75anQUu8uVl9IA8uabLSNJdzCfik2Mjbzs7/Kc hDJ4S0eJGIp2R7PWJUj0KdLyEP5853fGof6pfc1m8e0GCI/WCbPkEg7nRE6fqrXL n92sFCzVq8z8Ad6Up0CEB3lxW9purT39QVtvd56N9D2M8i8OMydIOOoZA0iQeBuI GcuJ6EC98Ul19QPdFCrk
=YYaa
-----END PGP SIGNATURE-----