public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] resolv/resolv.h: allow alternative resolv.conf files
@ 2017-08-17 11:50 Renzo Davoli
  2017-08-17 12:41 ` Florian Weimer
  2017-09-18 15:12 ` Florian Weimer
  0 siblings, 2 replies; 17+ messages in thread
From: Renzo Davoli @ 2017-08-17 11:50 UTC (permalink / raw)
  To: libc-alpha

In network namespaces (like vdens https://github.com/rd235/vdens) it is sometimes necessary to
define per-namespace resolver configurations.

The simple patch here attached permits the definition of an environment variabile to define the
path of the file to use instead of /etc/resolv.conf.

e.g.:
export PATH_RESCONF=/tmp/resolv.conf

2017-08-17 Renzo Davoli <renzo@cs.unibo.it>

diff --git a/resolv/resolv.h b/resolv/resolv.h
index e8c581ccd1..5e7a8143c3 100644
--- a/resolv/resolv.h
+++ b/resolv/resolv.h
@@ -91,7 +91,10 @@
  */
 
 #ifndef _PATH_RESCONF
-#define _PATH_RESCONF        "/etc/resolv.conf"
+#define _PATH_RESCONF        ({ \
+		char *path_resconf = getenv("PATH_RESCONF"); \
+		path_resconf ? path_resconf : "/etc/resolv.conf"; \
+		})
 #endif
 
 struct res_sym {

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] resolv/resolv.h: allow alternative resolv.conf files
  2017-08-17 11:50 [PATCH] resolv/resolv.h: allow alternative resolv.conf files Renzo Davoli
@ 2017-08-17 12:41 ` Florian Weimer
  2017-08-17 13:14   ` Zack Weinberg
  2017-09-18 15:12 ` Florian Weimer
  1 sibling, 1 reply; 17+ messages in thread
From: Florian Weimer @ 2017-08-17 12:41 UTC (permalink / raw)
  To: Renzo Davoli, libc-alpha

On 08/17/2017 01:50 PM, Renzo Davoli wrote:
> In network namespaces (like vdens https://github.com/rd235/vdens) it is sometimes necessary to
> define per-namespace resolver configurations.
> 
> The simple patch here attached permits the definition of an environment variabile to define the
> path of the file to use instead of /etc/resolv.conf.

_PATH_RESCONF really has to be a string literal, and you can't use a GNU
C extension in such a way in an installed header file.

The environment variable would have to be ignored in AT_SECURE mode, so
you have to use __libc_secure_getenv or put it into unsecvars.h.

I'm still not convinced that this is the right thing to do.  Can you
share more about your use case?  I would expect that containers already
provide sufficient flexibility to adjust what is in /etc/resolv.conf.

Thanks,
Florian

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] resolv/resolv.h: allow alternative resolv.conf files
  2017-08-17 12:41 ` Florian Weimer
@ 2017-08-17 13:14   ` Zack Weinberg
  2017-08-17 13:59     ` Renzo Davoli
  0 siblings, 1 reply; 17+ messages in thread
From: Zack Weinberg @ 2017-08-17 13:14 UTC (permalink / raw)
  To: Florian Weimer; +Cc: Renzo Davoli, GNU C Library

On Thu, Aug 17, 2017 at 8:41 AM, Florian Weimer <fweimer@redhat.com> wrote:
> On 08/17/2017 01:50 PM, Renzo Davoli wrote:
>> In network namespaces (like vdens https://github.com/rd235/vdens) it is sometimes necessary to
>> define per-namespace resolver configurations.
>>
>> The simple patch here attached permits the definition of an environment variabile to define the
>> path of the file to use instead of /etc/resolv.conf.
>
> _PATH_RESCONF really has to be a string literal, and you can't use a GNU
> C extension in such a way in an installed header file.
>
> The environment variable would have to be ignored in AT_SECURE mode, so
> you have to use __libc_secure_getenv or put it into unsecvars.h.
>
> I'm still not convinced that this is the right thing to do.  Can you
> share more about your use case?  I would expect that containers already
> provide sufficient flexibility to adjust what is in /etc/resolv.conf.

'ip netns exec NAMESPACE PROGRAM...' overlay-mounts
/etc/netns/NAMESPACE over /etc, I thought that was the Official
Convention for this sort of thing.

zw

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] resolv/resolv.h: allow alternative resolv.conf files
  2017-08-17 13:14   ` Zack Weinberg
@ 2017-08-17 13:59     ` Renzo Davoli
  2017-08-17 14:32       ` Renzo Davoli
  0 siblings, 1 reply; 17+ messages in thread
From: Renzo Davoli @ 2017-08-17 13:59 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: Florian Weimer, GNU C Library

> Can you share more about your use case?

Sure. I am a developer of VDE, Virtual Distributed Ethernet.

One of the main features of the new implementation (VDE4) are the vde namespaces.
(user namespaces, also for users not having root access).

Simply typing vdens and a VDE-locator of a network a user gets a new namespace
connected to that network.

So for example:
  $ vdens vxvde://
  $ ip addr
  1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
      link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
  2: vde0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
      link/ether 02:ef:ba:21:82:5a brd ff:ff:ff:ff:ff:ff
  
Users can configure their ip addresses, routing and use their favourite tools (both
		servers and clients).

As a complete example let us create a vde namespace connected to a remote slirp service:
  $ vdens cmd://'ssh vdetest.v2.cs.unibo.it vde_plug slirp://'
  $ /sbin/udhcpc -i vde0
  udhcpc (v1.22.1) started
  Sending discover...
  Sending select for 10.0.2.15...
  Lease of 10.0.2.15 obtained, lease time 86400
  $ ip link set lo up
  1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
      link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
		  inet 127.0.0.1/8 scope host o
		  valid_lft forever preferred_lft forever
		  inet6 ::1/128 scope host 
		  valid_lft forever preferred_lft forever
  2: vde0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 1000
      link/ether 7e:20:6e:12:f3:ee brd ff:ff:ff:ff:ff:ff
		  inet 10.0.2.15/24 brd 10.0.2.255 scope global vde0
		  valid_lft forever preferred_lft forever
		  inet6 fe80::7c20:6eff:fe12:f3ee/64 scope link 
		  valid_lft forever preferred_lft forever

Now a user can start any server or client... but if the nameserver defined in /etc/resolvconf (by root)
is not reachable all the resolv functions will fail. 

Why a user (not root) should not be allowed to choose her own resolver?
Why to obtain a so simple feature should I have to overlay mount /etc?

I have had the same problem in other project:
* libvdestack: provide processes their own netwoking stack(s)
https://github.com/rd235/libvdestack

* fqdndhcp: a dhcp server receiving the fully qualified domain name from the client and providing
it with the IP(v6) address retrieved fron a DNS server. In this way configuring hosts is as simple as
giving them a name. In this case it happens that sometimes specific DNS servers for the service get used, so
the daemon has to query them instead of the standard servers. I have currently solved this problem using libadns,
but all I needed was a way to use getaddrinfo using my own nameserver.
(see: https://github.com/rd235/vde_dnsutils/blob/master/resolv.c).

Any implementation/alternative approach/patch which fits the requirements (possibility to define the nameserver to use, 
no root access required) is okay to me.

Thank you.

	renzo

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] resolv/resolv.h: allow alternative resolv.conf files
  2017-08-17 13:59     ` Renzo Davoli
@ 2017-08-17 14:32       ` Renzo Davoli
  2017-08-17 15:21         ` Carlos O'Donell
  2017-08-17 16:13         ` Florian Weimer
  0 siblings, 2 replies; 17+ messages in thread
From: Renzo Davoli @ 2017-08-17 14:32 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: Florian Weimer, GNU C Library

> _PATH_RESCONF really has to be a string literal, and you can't use a GNU
> C extension in such a way in an installed header file.
> 
> The environment variable would have to be ignored in AT_SECURE mode, so
> you have to use __libc_secure_getenv or put it into unsecvars.h.

Here is a different implementation:
* it does not use any gcc extension
* use __libc_secure_getenv instead of getenv
* do not change installed header files.

Thank you.	
	renzo

2017-08-17 Renzo Davoli <renzo@cs.unibo.it>

diff --git a/resolv/res_init.c b/resolv/res_init.c
index fa46ce7813..bca60568ad 100644
--- a/resolv/res_init.c
+++ b/resolv/res_init.c
@@ -545,7 +545,7 @@ __resolv_conf_load (struct __res_state *preinit)
   /* Ensure that /etc/hosts.conf has been loaded (once).  */
   _res_hconf_init ();
 
-  FILE *fp = fopen (_PATH_RESCONF, "rce");
+  FILE *fp = fopen (__resolv_path_resconf(), "rce");
   if (fp == NULL)
     switch (errno)
       {
diff --git a/resolv/resolv-internal.h b/resolv/resolv-internal.h
index 32dc44777e..aa52497550 100644
--- a/resolv/resolv-internal.h
+++ b/resolv/resolv-internal.h
@@ -97,4 +97,8 @@ int __res_nopt (struct resolv_context *, int n0,
 int __inet_pton_length (int af, const char *src, size_t srclen, void *);
 libc_hidden_proto (__inet_pton_length)
 
+/* Return the current fileto use as resolv.conf 
+	 __PATH_RESCONF o the value of the env var PATH_RESCONF if it exists*/
+const char *__resolv_path_resconf(void);
+
 #endif  /* _RESOLV_INTERNAL_H */
diff --git a/resolv/resolv_conf.c b/resolv/resolv_conf.c
index f391d30c27..9896e64cdc 100644
--- a/resolv/resolv_conf.c
+++ b/resolv/resolv_conf.c
@@ -119,11 +119,19 @@ conf_decrement (struct resolv_conf *conf)
     free (conf);
 }
 
+const char *__resolv_path_resconf(void) {
+	char *path_resconf = __libc_secure_getenv("PATH_RESCONF");
+	if (path_resconf)
+		return path_resconf;
+	else
+		return _PATH_RESCONF;
+}
+
 struct resolv_conf *
 __resolv_conf_get_current (void)
 {
   struct stat64 st;
-  if (stat64 (_PATH_RESCONF, &st) != 0)
+  if (stat64 (__resolv_path_resconf(), &st) != 0)
     {
     switch (errno)
       {

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] resolv/resolv.h: allow alternative resolv.conf files
  2017-08-17 14:32       ` Renzo Davoli
@ 2017-08-17 15:21         ` Carlos O'Donell
  2017-08-17 16:18           ` Renzo Davoli
  2017-08-17 16:13         ` Florian Weimer
  1 sibling, 1 reply; 17+ messages in thread
From: Carlos O'Donell @ 2017-08-17 15:21 UTC (permalink / raw)
  To: Renzo Davoli, Zack Weinberg; +Cc: Florian Weimer, GNU C Library

On 08/17/2017 10:32 AM, Renzo Davoli wrote:
>> _PATH_RESCONF really has to be a string literal, and you can't use a GNU
>> C extension in such a way in an installed header file.
>>
>> The environment variable would have to be ignored in AT_SECURE mode, so
>> you have to use __libc_secure_getenv or put it into unsecvars.h.
> 
> Here is a different implementation:
> * it does not use any gcc extension
> * use __libc_secure_getenv instead of getenv
> * do not change installed header files.

You ask:

"Why to obtain a so simple feature should I have to overlay mount /etc?"

and the answer is:

* It complicates the glibc design when an overlay mount already exists.

* Environment variables are brittle and may be cleared in certain
  or unused in certain circumstances.

The most robust solution is an overlay mount in /etc.

Is there anything technically wrong with the overlay mount?

The overlay mount is semantically clearer than another env var that
changes existing behaviour.

-- 
Cheers,
Carlos.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] resolv/resolv.h: allow alternative resolv.conf files
  2017-08-17 14:32       ` Renzo Davoli
  2017-08-17 15:21         ` Carlos O'Donell
@ 2017-08-17 16:13         ` Florian Weimer
  2017-08-18 15:08           ` Renzo Davoli
  1 sibling, 1 reply; 17+ messages in thread
From: Florian Weimer @ 2017-08-17 16:13 UTC (permalink / raw)
  To: Renzo Davoli, Zack Weinberg; +Cc: GNU C Library

On 08/17/2017 04:32 PM, Renzo Davoli wrote:
>> _PATH_RESCONF really has to be a string literal, and you can't use a GNU
>> C extension in such a way in an installed header file.
>>
>> The environment variable would have to be ignored in AT_SECURE mode, so
>> you have to use __libc_secure_getenv or put it into unsecvars.h.
> 
> Here is a different implementation:

> * it does not use any gcc extension
> * use __libc_secure_getenv instead of getenv
> * do not change installed header files.

That's certainly better.  Do you have an example of another system which
offers a similar environment variable?

Thanks,
Florian

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] resolv/resolv.h: allow alternative resolv.conf files
  2017-08-17 15:21         ` Carlos O'Donell
@ 2017-08-17 16:18           ` Renzo Davoli
  2017-08-17 16:25             ` Florian Weimer
  0 siblings, 1 reply; 17+ messages in thread
From: Renzo Davoli @ 2017-08-17 16:18 UTC (permalink / raw)
  To: Carlos O'Donell; +Cc: Zack Weinberg, Florian Weimer, GNU C Library

On Thu, Aug 17, 2017 at 11:20:53AM -0400, Carlos O'Donell wrote:
> Is there anything technically wrong with the overlay mount?

Yes. AFAIK it requires CAP_SYS_ADMIN to mount.  (see clone(2) or unshare(2)).

Please tell me how to mount an overlay in a user namespace, this would give
a solution to my problem (although a sub-optimal one, it is much more complex 
to use than an env var, IMHO).

thank you in advance.

	renzo

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] resolv/resolv.h: allow alternative resolv.conf files
  2017-08-17 16:18           ` Renzo Davoli
@ 2017-08-17 16:25             ` Florian Weimer
  2017-08-17 16:49               ` Szabolcs Nagy
  0 siblings, 1 reply; 17+ messages in thread
From: Florian Weimer @ 2017-08-17 16:25 UTC (permalink / raw)
  To: Renzo Davoli, Carlos O'Donell; +Cc: Zack Weinberg, GNU C Library

On 08/17/2017 06:18 PM, Renzo Davoli wrote:
> On Thu, Aug 17, 2017 at 11:20:53AM -0400, Carlos O'Donell wrote:
>> Is there anything technically wrong with the overlay mount?
> 
> Yes. AFAIK it requires CAP_SYS_ADMIN to mount.  (see clone(2) or unshare(2)).
> 
> Please tell me how to mount an overlay in a user namespace, this would give
> a solution to my problem (although a sub-optimal one, it is much more complex 
> to use than an env var, IMHO).

resolv/tst-resolv-res_init-skeleton.c uses the support/ framework to
replace /etc in the test chroot, precisely because the /etc/resolv.conf
path is currently hard-coded.  The test does not need root permissions
to run on current Fedora, for instance.

Is this what you had in mind?

Thanks,
Florian

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] resolv/resolv.h: allow alternative resolv.conf files
  2017-08-17 16:25             ` Florian Weimer
@ 2017-08-17 16:49               ` Szabolcs Nagy
  2017-08-17 16:55                 ` Florian Weimer
  0 siblings, 1 reply; 17+ messages in thread
From: Szabolcs Nagy @ 2017-08-17 16:49 UTC (permalink / raw)
  To: Florian Weimer, Renzo Davoli, Carlos O'Donell
  Cc: nd, Zack Weinberg, GNU C Library

On 17/08/17 17:24, Florian Weimer wrote:
> resolv/tst-resolv-res_init-skeleton.c uses the support/ framework to
> replace /etc in the test chroot, precisely because the /etc/resolv.conf
> path is currently hard-coded.  The test does not need root permissions
> to run on current Fedora, for instance.

how does chroot work without root on fedora?

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] resolv/resolv.h: allow alternative resolv.conf files
  2017-08-17 16:49               ` Szabolcs Nagy
@ 2017-08-17 16:55                 ` Florian Weimer
  0 siblings, 0 replies; 17+ messages in thread
From: Florian Weimer @ 2017-08-17 16:55 UTC (permalink / raw)
  To: Szabolcs Nagy, Renzo Davoli, Carlos O'Donell
  Cc: nd, Zack Weinberg, GNU C Library

On 08/17/2017 06:48 PM, Szabolcs Nagy wrote:
> On 17/08/17 17:24, Florian Weimer wrote:
>> resolv/tst-resolv-res_init-skeleton.c uses the support/ framework to
>> replace /etc in the test chroot, precisely because the /etc/resolv.conf
>> path is currently hard-coded.  The test does not need root permissions
>> to run on current Fedora, for instance.
> 
> how does chroot work without root on fedora?

See support_become_root:

bool
support_become_root (void)
{
#ifdef CLONE_NEWUSER
  if (unshare (CLONE_NEWUSER | CLONE_NEWNS) == 0)
    /* Even if we do not have UID zero, we have extended privileges at
       this point.  */
    return true;
#endif
  if (setuid (0) != 0)
    {
      printf ("warning: could not become root outside namespace (%m)\n");
      return false;
    }
  return true;
}

Florian

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] resolv/resolv.h: allow alternative resolv.conf files
  2017-08-17 16:13         ` Florian Weimer
@ 2017-08-18 15:08           ` Renzo Davoli
  2017-08-18 16:41             ` Carlos O'Donell
  0 siblings, 1 reply; 17+ messages in thread
From: Renzo Davoli @ 2017-08-18 15:08 UTC (permalink / raw)
  To: Florian Weimer; +Cc: Zack Weinberg, GNU C Library

> That's certainly better.  Do you have an example of another system which
> offers a similar environment variable?
I don't know actually. I can search around.
Features similar to namespaces should exist in BSD and Solaris (zones).

I have found that someone else had a similar problem
https://github.com/hadess/resolvconf-override
This library rewrites _res.nsaddr_list[i]... which is more a dirty trick 
than a solution. It may break with future changes in glibc.

Queries for per-user configuration of resolv.conf can be found googling around:
e.g. using the key "per-user resolv.conf".

I have tested the proposals I got from this mailing list (thank you all!).

The code at the end of this message partially solves my problem.
It can be tested in this way:

$ gcc -o newresconf newresconf.c
$ echo nameserver 80.80.80.80 > /tmp/resolv.conf
$ cat /etc/resolv.conf
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
nameserver 127.0.0.1
$ PATH_RESCONF=/tmp/resolv.conf ./newresconf bash
$ cat /etc/resolv.conf
nameserver 80.80.80.80
$ exit

There are still issues: e.g. setuid does not work in this namespace so e.g. I got:
$ ping 127.0.0.1
ping: socket: Operation not permitted

I had to define a USER+NS namespace, remap uids and gids (which needs a separate process),
and finally mount-bind the file.

It seems a bizantine procedure just to tell resolv to use a different resolv.conf.
There is some extra work for the kernel (keep track of the new namespaces, separate mounttables,
more mount items) for a problem that could be solved entirely at user level.

resolv.conf is just a configuration file of the library. A security model based
on the idea that something is safe because the library forbids the access to a
functionality is weak. System calls must enforce processes to behave correctly,
system calls can really forbid bad behaviors. When a syscall says no it is no.
Users can run different libraries if it is just the library to deny something.

So, why not providing a linear and straightforward simple way to solve a simple problem?

Providing complex methods only, does not make the system safer but prevents developers
from writing services or at least from writing good clean code to implement their services.
Isn't it?

(just my 2 euro cents).

thank you

	renzo

/* 
 * newresconf: experimental code. bind /etc/resolv.conf to a different file.
 * code inspired by vdens GPLv2+ by Renzo Davoli et al.
 */

#define _GNU_SOURCE
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sched.h>
#include <limits.h>
#include <errno.h>
#include <sys/capability.h>
#include <sys/prctl.h>
#include <sys/mount.h>

#define errExit(msg)    ({ perror(msg); exit(EXIT_FAILURE); })

static void uid_gid_map(pid_t pid) {
	char map_file[PATH_MAX];
	FILE *f;
	uid_t euid = geteuid();
	gid_t egid = getegid();
	snprintf(map_file, PATH_MAX, "/proc/%d/uid_map", pid);
	f = fopen(map_file, "w");
	if (f) {
		fprintf(f,"%d %d 1\n",euid,euid);
		fclose(f);
	}
	snprintf(map_file, PATH_MAX, "/proc/%d/setgroups", pid);
	f = fopen(map_file, "w");
	if (f) {
		fprintf(f,"deny\n");
		fclose(f);
	}
	snprintf(map_file, PATH_MAX, "/proc/%d/gid_map", pid);
	f = fopen(map_file, "w");
	if (f) {
		fprintf(f,"%d %d 1\n",egid,egid);
		fclose(f);
	}
}

static void unsharens(void) {
	int pipe_fd[2];
	pid_t child_pid;
	char buf[1];
	if (pipe2(pipe_fd, O_CLOEXEC) == -1)
		errExit("pipe");
	switch (child_pid = fork()) {
		case 0:
			close(pipe_fd[1]);
			read(pipe_fd[0], &buf, sizeof(buf));
			uid_gid_map(getppid());
			exit(0);
		default:
			close(pipe_fd[0]);
			if (unshare(CLONE_NEWUSER | CLONE_NEWNS) == -1)
				errExit("unshare");
			close(pipe_fd[1]);
			if (waitpid(child_pid, NULL, 0) == -1)      /* Wait for child */
				errExit("waitpid");
			break;
		case -1:
			errExit("unshare fork");
	}
}

void new_resolv_conf(const char *path_resconf) {

	if (path_resconf && *path_resconf) {
		unsharens();
		if (mount(path_resconf, "/etc/resolv.conf", "", MS_MGC_VAL|MS_BIND, NULL) < 0)
			errExit("mount");
	}
}

int main(int argc, char *argv[])
{
	char **cmdargv;
	char *argvsh[]={getenv("SHELL"),NULL};

	if (argc == 1)
		cmdargv = argvsh;
	else
		cmdargv = argv + 1;

	if (cmdargv[0] == NULL) {
		fprintf(stderr, "Error: $SHELL env variable not set\n");
		exit(EXIT_FAILURE); 
	}

	new_resolv_conf(getenv("PATH_RESCONF"));

	execvp(cmdargv[0], cmdargv);

	exit(EXIT_SUCCESS);
}

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] resolv/resolv.h: allow alternative resolv.conf files
  2017-08-18 15:08           ` Renzo Davoli
@ 2017-08-18 16:41             ` Carlos O'Donell
  2017-08-22  9:37               ` Renzo Davoli
  0 siblings, 1 reply; 17+ messages in thread
From: Carlos O'Donell @ 2017-08-18 16:41 UTC (permalink / raw)
  To: Renzo Davoli, Florian Weimer; +Cc: Zack Weinberg, GNU C Library

On 08/18/2017 11:07 AM, Renzo Davoli wrote:
> It seems a bizantine procedure just to tell resolv to use a different
> resolv.conf.

I agree, but that's not the extent of this...

It is not just about resolv.conf, the point is to avoid all the other
problems you may also run into. The point is to provide you with a robust
solution so you don't have to come back for all the other environment
variables you may need to tweak the runtime.

For each of these environment variables there is security risk, auditing
issues, maintenance costs etc.

> There is some extra work for the kernel (keep track of the new
> namespaces, separate mounttables, more mount items) for a problem
> that could be solved entirely at user level.

Yes, you are right.

You are paying the cost for a design abstraction.

Design abstractions make it easier for your users to know how your
systems work without needing to learn something new e.g. a new
environment variable.

> resolv.conf is just a configuration file of the library. A security
> model based on the idea that something is safe because the library
> forbids the access to a functionality is weak. System calls must
> enforce processes to behave correctly, system calls can really forbid
> bad behaviors. When a syscall says no it is no. Users can run
> different libraries if it is just the library to deny something.

Reductio ad absurdum is not valid here, there are layers of security
and core userspace libraries play a key role here in providing security.
 
> So, why not providing a linear and straightforward simple way to
> solve a simple problem?

It adds to the overall complexity of the library, and makes it harder
to know how to correctly configure your application and know exactly
where it will get resolver information from.

Users are already deploying containers to solve other problems and
if your solution dovetails nicely into this, then they will appreciate
that.

> Providing complex methods only, does not make the system safer but
> prevents developers from writing services or at least from writing
> good clean code to implement their services. Isn't it?

Making there only be 1 way to set the resolver configuration makes it
easier for application developers, and administrator to administer
their systems.

Using namespaces, including mount namespaces, could be made easier.
There is an argument for that, but this argument should not apply
as the reason for making there be 2 ways to set the resolver information.
This complicates configuration and debugging for users.

If anything I would focus on making namespace easier :-)

--
Cheers,
Carlos.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] resolv/resolv.h: allow alternative resolv.conf files
  2017-08-18 16:41             ` Carlos O'Donell
@ 2017-08-22  9:37               ` Renzo Davoli
  2017-08-23  4:07                 ` Carlos O'Donell
  0 siblings, 1 reply; 17+ messages in thread
From: Renzo Davoli @ 2017-08-22  9:37 UTC (permalink / raw)
  To: Carlos O'Donell; +Cc: Florian Weimer, Zack Weinberg, GNU C Library

I have released userbindconf, a library and a utility command to
bind-mount files and directores in user-namespaces.
https://github.com/rd235/userbindmount

Nevertheless, the whole stuff sounds as a workaround to me.

On Fri, Aug 18, 2017 at 12:41:50PM -0400, Carlos O'Donell wrote:
> On 08/18/2017 11:07 AM, Renzo Davoli wrote:
> > It seems a bizantine procedure just to tell resolv to use a different
> > resolv.conf.
> I agree, but that's not the extent of this...
...
> > There is some extra work for the kernel (keep track of the new
> > namespaces, separate mounttables, more mount items) for a problem
> > that could be solved entirely at user level.
> Yes, you are right.
> You are paying the cost for a design abstraction.
> 
> Design abstractions make it easier for your users to know how your
> systems work without needing to learn something new e.g. a new
> environment variable.

An abstraction should be a simple concept able to represent a wide
range of situations. Astractions should be simpler than the 
"abstracted" concepts.

Using complicated methods to override a lack of generalization of
the lower layer is more a "distraction" than an "abstraction".

There are several environment variables already in glibc to
configure the name resolving process:
RES_OPTIONS, RESOLV_ADD_TRIM_DOMAINS RESOLV_MULTI 
RESOLV_OVERRIDE_TRIM_DOMAINS RESOLV_REORDER 
RESOLV_SERV_ORDER RESOLV_SPOOF_CHECK 

What to say about:
RESOLV_HOST_CONF
?

It redefines the path to be used instead of /etc/host.conf.
Isn't this very close to what I proposed as PATH_RESCONF?
(which could be renamed as RESOLV_RESCONF to be consistent
 with the others).

Is there really the need for a user-namespace for a so simple
(and common) generalization?
Timezones and locales should be implemented as "abstractions"
requiring namespaces if this is the idea, isn't it?
Try to think on how complex would be the management of
timezones and locales it this was the case...

Thank you

	renzo

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] resolv/resolv.h: allow alternative resolv.conf files
  2017-08-22  9:37               ` Renzo Davoli
@ 2017-08-23  4:07                 ` Carlos O'Donell
  0 siblings, 0 replies; 17+ messages in thread
From: Carlos O'Donell @ 2017-08-23  4:07 UTC (permalink / raw)
  To: Renzo Davoli; +Cc: Florian Weimer, Zack Weinberg, GNU C Library

On 08/22/2017 05:37 AM, Renzo Davoli wrote:
> I have released userbindconf, a library and a utility command to
> bind-mount files and directores in user-namespaces.
> https://github.com/rd235/userbindmount
> 
> Nevertheless, the whole stuff sounds as a workaround to me.
> 
> On Fri, Aug 18, 2017 at 12:41:50PM -0400, Carlos O'Donell wrote:
>> On 08/18/2017 11:07 AM, Renzo Davoli wrote:
>>> It seems a bizantine procedure just to tell resolv to use a different
>>> resolv.conf.
>> I agree, but that's not the extent of this...
> ...
>>> There is some extra work for the kernel (keep track of the new
>>> namespaces, separate mounttables, more mount items) for a problem
>>> that could be solved entirely at user level.
>> Yes, you are right.
>> You are paying the cost for a design abstraction.
>>
>> Design abstractions make it easier for your users to know how your
>> systems work without needing to learn something new e.g. a new
>> environment variable.
> 
> An abstraction should be a simple concept able to represent a wide
> range of situations. Astractions should be simpler than the 
> "abstracted" concepts.

I agree.

> Using complicated methods to override a lack of generalization of
> the lower layer is more a "distraction" than an "abstraction".

There is a difference between the high-level abstraction and how it
is implemented. You may not like the complexity of the present
implementation, but the abstraction remains.

> There are several environment variables already in glibc to
> configure the name resolving process:
> RES_OPTIONS, RESOLV_ADD_TRIM_DOMAINS RESOLV_MULTI 
> RESOLV_OVERRIDE_TRIM_DOMAINS RESOLV_REORDER 
> RESOLV_SERV_ORDER RESOLV_SPOOF_CHECK 
> 
> What to say about:
> RESOLV_HOST_CONF
> ?

They exist because there was no other per-process solution, and
because glibc is backwards compatible we must keep them forever.

That doesn't mean they are a good design for today.

> It redefines the path to be used instead of /etc/host.conf.
> Isn't this very close to what I proposed as PATH_RESCONF?
> (which could be renamed as RESOLV_RESCONF to be consistent
>  with the others).

Yes it does.
 
> Is there really the need for a user-namespace for a so simple
> (and common) generalization?

Need is difficult to answer. There are performance, maintenance,
and security implications to take into account.

> Timezones and locales should be implemented as "abstractions"
> requiring namespaces if this is the idea, isn't it?
> Try to think on how complex would be the management of
> timezones and locales it this was the case...

Reductio ad absurdium should not be used to argue the technical
merits of a new interface, the old interface already exists and
may not be a good example of modern design.

Locales *are* being implemented in containers exactly how you
envision them. Thin containers provisioned with only C.UTF-8
(which several distros offer) are setup to provide microservices
which never need other locales (reduces QA and testing).

The locale, timezone, and resolver states can all be made
thread-local. This makes it harder to avoid providing all locales
for selection by threads which need specific languages to provide
those services in the language needed. Similarly some threads may
operate on different timezone data and so need all the timezone
data. Lastly, likewise different threads could use different
resolver state, you just need to configure it.

I see three solutions present today:

(a) Per-thread: Modify _res to get per-thread state. May go away
    some day, but backwards binary compat will always exist.

(b) Per-process / Per-thread:
    Alternate resolver library e.g. flexible DNS client library.
    The glibc resolver API is a standards compatible no-frills stub
    resolver.

(c) Per-process: mount namespace which overrides /etc/resolv.conf
    for your process.

-- 
Cheers,
Carlos.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] resolv/resolv.h: allow alternative resolv.conf files
  2017-08-17 11:50 [PATCH] resolv/resolv.h: allow alternative resolv.conf files Renzo Davoli
  2017-08-17 12:41 ` Florian Weimer
@ 2017-09-18 15:12 ` Florian Weimer
  2017-09-18 15:27   ` Carlos O'Donell
  1 sibling, 1 reply; 17+ messages in thread
From: Florian Weimer @ 2017-09-18 15:12 UTC (permalink / raw)
  To: Renzo Davoli, libc-alpha

My main concern at this point is that a lot of software hard-codes the 
/etc/resolv.conf path and parses the file on its own, to obtain the 
search path and the configured name servers.

Once we add an environment variable to change the path, that's going to 
add a lot of confusion because the system will have an inconsistent view 
on the data.  I do not have a good answer to that.

Thanks,
Florian

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH] resolv/resolv.h: allow alternative resolv.conf files
  2017-09-18 15:12 ` Florian Weimer
@ 2017-09-18 15:27   ` Carlos O'Donell
  0 siblings, 0 replies; 17+ messages in thread
From: Carlos O'Donell @ 2017-09-18 15:27 UTC (permalink / raw)
  To: Florian Weimer, Renzo Davoli, libc-alpha

On 09/18/2017 09:12 AM, Florian Weimer wrote:
> My main concern at this point is that a lot of software hard-codes
> the /etc/resolv.conf path and parses the file on its own, to obtain
> the search path and the configured name servers.
> 
> Once we add an environment variable to change the path, that's going
> to add a lot of confusion because the system will have an
> inconsistent view on the data.  I do not have a good answer to that.

Restating my position from August 18th (up thread):

Making there only be 1 way to set the resolver configuration makes it
easier for application developers, and administrators to manage and
develop such systems.

The only remaining alternative is to have glibc become responsible for
maintaining the consistency between /etc/resolv.conf and the env var.
It would require hiding the difference to the application using one
or other complex implementations e.g. mount namespace, hijacked open,
etc. I don't see a good tradeoff between the value of the new feature
and the complexity of the implementation. Higher level frameworks
will likely already need mount namespaces for other reasons so it
makes sense to delegate the normal system configuration to those
frameworks.

-- 
Cheers,
Carlos.

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2017-09-18 15:27 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-08-17 11:50 [PATCH] resolv/resolv.h: allow alternative resolv.conf files Renzo Davoli
2017-08-17 12:41 ` Florian Weimer
2017-08-17 13:14   ` Zack Weinberg
2017-08-17 13:59     ` Renzo Davoli
2017-08-17 14:32       ` Renzo Davoli
2017-08-17 15:21         ` Carlos O'Donell
2017-08-17 16:18           ` Renzo Davoli
2017-08-17 16:25             ` Florian Weimer
2017-08-17 16:49               ` Szabolcs Nagy
2017-08-17 16:55                 ` Florian Weimer
2017-08-17 16:13         ` Florian Weimer
2017-08-18 15:08           ` Renzo Davoli
2017-08-18 16:41             ` Carlos O'Donell
2017-08-22  9:37               ` Renzo Davoli
2017-08-23  4:07                 ` Carlos O'Donell
2017-09-18 15:12 ` Florian Weimer
2017-09-18 15:27   ` Carlos O'Donell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).