All of lore.kernel.org
 help / color / mirror / Atom feed
From: ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org (Eric W. Biederman)
To: "Nicolas François"
	<nicolas.francois-Fa7rcPG4DJn7nK0/Xc0eeg@public.gmane.org>
Cc: Linux Containers
	<containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org>,
	Pkg-shadow-devel-XbBxUvOt3X2LieD7tvxI8l/i77bcL1HB@public.gmane.org,
	"Michael Kerrisk (man-pages)"
	<mtk.manpages-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Subject: [PATCH 04/11] Add backend support for suboridnate uids and gids
Date: Tue, 22 Jan 2013 01:14:35 -0800	[thread overview]
Message-ID: <87liblr344.fsf@xmission.com> (raw)
In-Reply-To: <87d2wxshu0.fsf-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org> (Eric W. Biederman's message of "Tue, 22 Jan 2013 01:11:19 -0800")


These files list the set of subordinate uids and gids that users are allowed
to use.   The expect use case is with the user namespace but other uses are
allowed.

Signed-off-by: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>
---
 etc/login.defs      |    8 +
 lib/Makefile.am     |    2 +
 lib/getdef.c        |    6 +
 lib/subordinateio.c |  512 +++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/subordinateio.h |   38 ++++
 5 files changed, 566 insertions(+), 0 deletions(-)
 create mode 100644 lib/subordinateio.c
 create mode 100644 lib/subordinateio.h

diff --git a/etc/login.defs b/etc/login.defs
index 5b6fab3..01a0089 100644
--- a/etc/login.defs
+++ b/etc/login.defs
@@ -226,6 +226,10 @@ UID_MAX			60000
 # System accounts
 SYS_UID_MIN		  101
 SYS_UID_MAX		  999
+# Extra per user uids
+SUB_UID_MIN		   100000
+SUB_UID_MAX		600100000
+SUB_UID_COUNT		    10000
 
 #
 # Min/max values for automatic gid selection in groupadd
@@ -235,6 +239,10 @@ GID_MAX			60000
 # System accounts
 SYS_GID_MIN		  101
 SYS_GID_MAX		  999
+# Extra per user group ids
+SUB_GID_MIN		   100000
+SUB_GID_MAX		600100000
+SUB_GID_COUNT		    10000
 
 #
 # Max number of login retries if password is bad
diff --git a/lib/Makefile.am b/lib/Makefile.am
index c448dd3..6db86cd 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -39,6 +39,8 @@ libshadow_la_SOURCES = \
 	pwio.c \
 	pwio.h \
 	pwmem.c \
+	subordinateio.h \
+	subordinateio.c \
 	selinux.c \
 	semanage.c \
 	sgetgrent.c \
diff --git a/lib/getdef.c b/lib/getdef.c
index ac08163..f872bb3 100644
--- a/lib/getdef.c
+++ b/lib/getdef.c
@@ -81,6 +81,12 @@ static struct itemdef def_table[] = {
 	{"SHA_CRYPT_MAX_ROUNDS", NULL},
 	{"SHA_CRYPT_MIN_ROUNDS", NULL},
 #endif
+	{"SUB_GID_COUNT", NULL},
+	{"SUB_GID_MAX", NULL},
+	{"SUB_GID_MIN", NULL},
+	{"SUB_UID_COUNT", NULL},
+	{"SUB_UID_MAX", NULL},
+	{"SUB_UID_MIN", NULL},
 	{"SULOG_FILE", NULL},
 	{"SU_NAME", NULL},
 	{"SYS_GID_MAX", NULL},
diff --git a/lib/subordinateio.c b/lib/subordinateio.c
new file mode 100644
index 0000000..851cfa0
--- /dev/null
+++ b/lib/subordinateio.c
@@ -0,0 +1,512 @@
+/*
+ * Copyright (c) 2012 - Eric Biederman
+ */
+
+#include <config.h>
+#include "prototypes.h"
+#include "defines.h"
+#include <stdio.h>
+#include "commonio.h"
+#include "subordinateio.h"
+
+struct subordinate_range {
+	const char *owner;
+	unsigned long start;
+	unsigned long count;
+};
+
+#define NFIELDS 3
+
+static /*@null@*/ /*@only@*/void *subordinate_dup (const void *ent)
+{
+	const struct subordinate_range *rangeent = ent;
+	struct subordinate_range *range;
+
+	range = (struct subordinate_range *) malloc (sizeof *range);
+	if (NULL == range) {
+		return NULL;
+	}
+	range->owner = strdup (rangeent->owner);
+	if (NULL == range->owner) {
+		free(range);
+		return NULL;
+	}
+	range->start = rangeent->start;
+	range->count = rangeent->count;
+
+	return range;
+}
+
+static void subordinate_free (/*@out@*/ /*@only@*/void *ent)
+{
+	struct subordinate_range *rangeent = ent;
+	
+	free ((void *)(rangeent->owner));
+	free (rangeent);
+}
+
+static void *subordinate_parse (const char *line)
+{
+	static struct subordinate_range range;
+	char rangebuf[1024];
+	int i;
+	char *cp;
+	char *fields[NFIELDS];
+
+	/*
+	 * Copy the string to a temporary buffer so the substrings can
+	 * be modified to be NULL terminated.
+	 */
+	if (strlen (line) >= sizeof rangebuf)
+		return NULL;	/* fail if too long */
+	strcpy (rangebuf, line);
+
+	/*
+	 * Save a pointer to the start of each colon separated
+	 * field.  The fields are converted into NUL terminated strings.
+	 */
+
+	for (cp = rangebuf, i = 0; (i < NFIELDS) && (NULL != cp); i++) {
+		fields[i] = cp;
+		while (('\0' != *cp) && (':' != *cp)) {
+			cp++;
+		}
+
+		if ('\0' != *cp) {
+			*cp = '\0';
+			cp++;
+		} else {
+			cp = NULL;
+		}
+	}
+
+	/*
+	 * There must be exactly NFIELDS colon separated fields or
+	 * the entry is invalid.  Also, fields must be non-blank.
+	 */
+	if (i != NFIELDS || *fields[0] == '\0' || *fields[1] == '\0' || *fields[2] == '\0')
+		return NULL;
+	range.owner = fields[0];
+	if (getulong (fields[1], &range.start) == 0)
+		return NULL;
+	if (getulong (fields[2], &range.count) == 0)
+		return NULL;
+
+	return &range;
+}
+
+static int subordinate_put (const void *ent, FILE * file)
+{
+	const struct subordinate_range *range = ent;
+
+	return fprintf(file, "%s:%lu:%lu\n",
+			       range->owner,
+			       range->start,
+			       range->count) < 0 ? -1  : 0;
+}
+
+static struct commonio_ops subordinate_ops = {
+	subordinate_dup,	/* dup */
+	subordinate_free,	/* free */
+	NULL,			/* getname */
+	subordinate_parse,	/* parse */
+	subordinate_put,	/* put */
+	fgets,			/* fgets */
+	fputs,			/* fputs */
+	NULL,			/* open_hook */
+	NULL,			/* close_hook */
+};
+
+static /*@observer@*/ /*@null*/const struct subordinate_range *subordinate_next(struct commonio_db *db)
+{
+	commonio_next (db);
+}
+
+static bool is_range_free(struct commonio_db *db, unsigned long start,
+			  unsigned long count)
+{
+	const struct subordinate_range *range;
+	unsigned long end = start + count - 1;
+
+	commonio_rewind(db);
+	while ((range = commonio_next(db)) != NULL) {
+		unsigned long first = range->start;
+		unsigned long last = first + range->count - 1;
+
+		if ((end >= first) && (start <= last))
+			return false;
+	}
+	return true;
+}
+
+static const bool range_exists(struct commonio_db *db, const char *owner)
+{
+	const struct subordinate_range *range;
+	commonio_rewind(db);
+	while ((range = commonio_next(db)) != NULL) {
+		unsigned long first = range->start;
+		unsigned long last = first + range->count - 1;
+
+		if (0 == strcmp(range->owner, owner))
+			return true;
+	}
+	return false;
+}
+
+static const struct subordinate_range *find_range(struct commonio_db *db,
+						  const char *owner, unsigned long val)
+{
+	const struct subordinate_range *range;
+	commonio_rewind(db);
+	while ((range = commonio_next(db)) != NULL) {
+		unsigned long first = range->start;
+		unsigned long last = first + range->count - 1;
+
+		if (0 != strcmp(range->owner, owner))
+			continue;
+
+		if ((val >= first) && (val <= last))
+			return range;
+	}
+	return NULL;
+}
+
+static bool have_range(struct commonio_db *db,
+		       const char *owner, unsigned long start, unsigned long count)
+{
+	const struct subordinate_range *range;
+	unsigned long end;
+
+	if (count == 0)
+		return false;
+
+	end = start + count - 1;
+	range = find_range (db, owner, start);
+	while (range) {
+		unsigned long last; 
+
+		last = range->start + range->count - 1;
+		if (last >= (start + count - 1))
+			return true;
+
+		count = end - last;
+		start = last + 1;
+		range = find_range(db, owner, start);
+	}
+	return false;
+}
+
+static int subordinate_range_cmp (const void *p1, const void *p2)
+{
+	struct subordinate_range *range1, *range2;
+
+	if ((*(struct commonio_entry **) p1)->eptr == NULL)
+		return 1;
+	if ((*(struct commonio_entry **) p2)->eptr == NULL)
+		return -1;
+
+	range1 = ((struct subordinate_range *) (*(struct commonio_entry **) p1)->eptr);
+	range2 = ((struct subordinate_range *) (*(struct commonio_entry **) p2)->eptr);
+
+	if (range1->start < range2->start)
+		return -1;
+	else if (range1->start > range2->start)
+		return 1;
+	else if (range1->count < range2->count)
+		return -1;
+	else if (range1->count > range2->count)
+		return 1;
+	else
+		return strcmp(range1->owner, range2->owner);
+}
+
+static unsigned long find_free_range(struct commonio_db *db,
+				     unsigned long min, unsigned long max,
+				     unsigned long count)
+{
+	const struct subordinate_range *range;
+	unsigned long low, high;
+
+	/* When given invalid parameters fail */
+	if ((count == 0) || (max <= min))
+		goto fail;
+
+	/* Sort by range than by owner */
+	commonio_sort (db, subordinate_range_cmp);
+	commonio_rewind(db);
+
+	low = min;
+	while ((range = commonio_next(db)) != NULL) {
+		unsigned long first = range->start;
+		unsigned long last = first + range->count - 1;
+
+		/* Find the top end of the hole before this range */
+		high = first;
+		if (high > max)
+			high = max;
+
+		/* Is the hole before this range large enough? */
+		if ((high > low) && (((high - low) + 1) >= count))
+			return low;
+
+		/* Compute the low end of the next hole */
+		if (low < (last + 1))
+			low = last + 1;
+		if (low > max)
+			goto fail;
+	}
+
+	/* Is the remaining unclaimed area large enough? */
+	if (((max - low) + 1) >= count)
+		return low;
+fail:
+	return ULONG_MAX;
+}
+
+static int add_range(struct commonio_db *db,
+	const char *owner, unsigned long start, unsigned long count)
+{
+	struct subordinate_range range;
+	range.owner = owner;
+	range.start = start;
+	range.count = count;
+
+	/* See if the range is already present */
+	if (have_range(db, owner, start, count))
+		return 1;
+
+	/* Oterwise append the range */
+	return commonio_append(db, &range);
+}
+
+static int remove_range(struct commonio_db *db,
+	const char *owner, unsigned long start, unsigned long count)
+{
+	struct commonio_entry *ent;
+	unsigned long end;
+
+	if (count == 0)
+		return 1;
+
+	end = start + count - 1;
+	for (ent = db->head; ent; ent = ent->next) {
+		struct subordinate_range *range = ent->eptr;
+		unsigned long first;
+		unsigned long last;
+
+		/* Skip unparsed entries */
+		if (!range)
+			continue;
+
+		first = range->start;
+		last = first + range->count - 1;
+
+		/* Skip entries with a different owner */
+		if (0 != strcmp(range->owner, owner))
+			continue;
+
+		/* Skip entries outside of the range to remove */
+		if ((end < first) || (start > last))
+			continue;
+
+		/* Is entry completely contained in the range to remove? */
+		if ((start <= first) && (end >= last)) {
+			commonio_del_entry (db, ent);
+		} 
+		/* Is just the start of the entry removed? */
+		else if ((start <= first) && (end < last)) {
+			range->start = end + 1;
+			range->count = (last - range->start) + 1;
+
+			ent->changed = true;
+		}
+		/* Is just the end of the entry removed? */
+		else if ((start > first) && (end >= last)) {
+			range->count = (start - range->start) + 1;
+
+			ent->changed = true;
+		}
+		/* The middle of the range is removed */
+		else {
+			struct subordinate_range tail;
+			tail.owner = range->owner;
+			tail.start = end + 1;
+			tail.count = (last - tail.start) + 1;
+
+			if (!commonio_append(db, &tail))
+				return 0;
+
+			range->count = (start - range->start) + 1;
+
+			ent->changed = true;
+		}
+	}
+
+	return 1;
+}
+
+static struct commonio_db subordinate_uid_db = {
+	"/etc/subuid",		/* filename */
+	&subordinate_ops,	/* ops */
+	NULL,			/* fp */
+#ifdef WITH_SELINUX
+	NULL,			/* scontext */
+#endif
+	NULL,			/* head */
+	NULL,			/* tail */
+	NULL,			/* cursor */
+	false,			/* changed */
+	false,			/* isopen */
+	false,			/* locked */
+	false			/* readonly */
+};
+
+int sub_uid_setdbname (const char *filename)
+{
+	return commonio_setname (&subordinate_uid_db, filename);
+}
+
+/*@observer@*/const char *sub_uid_dbname (void)
+{
+	return subordinate_uid_db.filename;
+}
+
+bool sub_uid_file_present (void)
+{
+	return commonio_present (&subordinate_uid_db);
+}
+
+int sub_uid_lock (void)
+{
+	return commonio_lock (&subordinate_uid_db);
+}
+
+int sub_uid_open (int mode)
+{
+	return commonio_open (&subordinate_uid_db, mode);
+}
+
+bool is_sub_uid_range_free(uid_t start, unsigned long count)
+{
+	return is_range_free (&subordinate_uid_db, start, count);
+}
+
+bool sub_uid_assigned(const char *owner)
+{
+	return range_exists (&subordinate_uid_db, owner);
+}
+
+bool have_sub_uids(const char *owner, uid_t start, unsigned long count)
+{
+	return have_range (&subordinate_uid_db, owner, start, count);
+}
+
+int sub_uid_add (const char *owner, uid_t start, unsigned long count)
+{
+	return add_range (&subordinate_uid_db, owner, start, count);
+}
+
+int sub_uid_remove (const char *owner, uid_t start, unsigned long count)
+{
+	return remove_range (&subordinate_uid_db, owner, start, count);
+}
+
+int sub_uid_close (void)
+{
+	return commonio_close (&subordinate_uid_db);
+}
+
+int sub_uid_unlock (void)
+{
+	return commonio_unlock (&subordinate_uid_db);
+}
+
+uid_t sub_uid_find_free_range(uid_t min, uid_t max, unsigned long count)
+{
+	unsigned long start;
+	start = find_free_range (&subordinate_uid_db, min, max, count);
+	return start == ULONG_MAX ? (uid_t) -1 : start;
+}
+
+static struct commonio_db subordinate_gid_db = {
+	"/etc/subgid",		/* filename */
+	&subordinate_ops,	/* ops */
+	NULL,			/* fp */
+#ifdef WITH_SELINUX
+	NULL,			/* scontext */
+#endif
+	NULL,			/* head */
+	NULL,			/* tail */
+	NULL,			/* cursor */
+	false,			/* changed */
+	false,			/* isopen */
+	false,			/* locked */
+	false			/* readonly */
+};
+
+int sub_gid_setdbname (const char *filename)
+{
+	return commonio_setname (&subordinate_gid_db, filename);
+}
+
+/*@observer@*/const char *sub_gid_dbname (void)
+{
+	return subordinate_gid_db.filename;
+}
+
+bool sub_gid_file_present (void)
+{
+	return commonio_present (&subordinate_gid_db);
+}
+
+int sub_gid_lock (void)
+{
+	return commonio_lock (&subordinate_gid_db);
+}
+
+int sub_gid_open (int mode)
+{
+	return commonio_open (&subordinate_gid_db, mode);
+}
+
+bool is_sub_gid_range_free(gid_t start, unsigned long count)
+{
+	return is_range_free (&subordinate_gid_db, start, count);
+}
+
+bool have_sub_gids(const char *owner, gid_t start, unsigned long count)
+{
+	return have_range(&subordinate_gid_db, owner, start, count);
+}
+
+bool sub_gid_assigned(const char *owner)
+{
+	return range_exists (&subordinate_gid_db, owner);
+}
+
+int sub_gid_add (const char *owner, gid_t start, unsigned long count)
+{
+	return add_range (&subordinate_gid_db, owner, start, count);
+}
+
+int sub_gid_remove (const char *owner, gid_t start, unsigned long count)
+{
+	return remove_range (&subordinate_gid_db, owner, start, count);
+}
+
+int sub_gid_close (void)
+{
+	return commonio_close (&subordinate_gid_db);
+}
+
+int sub_gid_unlock (void)
+{
+	return commonio_unlock (&subordinate_gid_db);
+}
+
+gid_t sub_gid_find_free_range(gid_t min, gid_t max, unsigned long count)
+{
+	unsigned long start;
+	start = find_free_range (&subordinate_gid_db, min, max, count);
+	return start == ULONG_MAX ? (gid_t) -1 : start;
+}
diff --git a/lib/subordinateio.h b/lib/subordinateio.h
new file mode 100644
index 0000000..f27b3c0
--- /dev/null
+++ b/lib/subordinateio.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2012- Eric W. Biederman
+ */
+
+#ifndef _SUBORDINATEIO_H
+#define _SUBORDINATEIO_H
+
+#include <sys/types.h>
+
+extern int sub_uid_close(void);
+extern bool is_sub_uid_range_free(uid_t start, unsigned long count);
+extern bool have_sub_uids(const char *owner, uid_t start, unsigned long count);
+extern bool sub_uid_file_present (void);
+extern bool sub_uid_assigned(const char *owner);
+extern int sub_uid_lock (void);
+extern int sub_uid_setdbname (const char *filename);
+extern /*@observer@*/const char *sub_uid_dbname (void);
+extern int sub_uid_open (int mode);
+extern int sub_uid_unlock (void);
+extern int sub_uid_add (const char *owner, uid_t start, unsigned long count);
+extern int sub_uid_remove (const char *owner, uid_t start, unsigned long count);
+extern uid_t sub_uid_find_free_range(uid_t min, uid_t max, unsigned long count);
+
+extern int sub_gid_close(void);
+extern bool is_sub_gid_range_free(gid_t start, unsigned long count);
+extern bool have_sub_gids(const char *owner, gid_t start, unsigned long count);
+extern bool sub_gid_file_present (void);
+extern bool sub_gid_assigned(const char *owner);
+extern int sub_gid_lock (void);
+extern int sub_gid_setdbname (const char *filename);
+extern /*@observer@*/const char *sub_gid_dbname (void);
+extern int sub_gid_open (int mode);
+extern int sub_gid_unlock (void);
+extern int sub_gid_add (const char *owner, gid_t start, unsigned long count);
+extern int sub_gid_remove (const char *owner, gid_t start, unsigned long count);
+extern uid_t sub_gid_find_free_range(gid_t min, gid_t max, unsigned long count);
+
+#endif
-- 
1.7.5.4

  parent reply	other threads:[~2013-01-22  9:14 UTC|newest]

Thread overview: 59+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-01-22  9:11 [PATCH 00/11] pkg-shadow support subordinate ids with user namespaces Eric W. Biederman
     [not found] ` <87d2wxshu0.fsf-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>
2013-01-22  9:12   ` [PATCH 01/11] Documentation for /etc/subuid and /etc/subgid Eric W. Biederman
2013-01-22  9:12   ` [PATCH 02/11] login.defs.5: Document the new variables in login.defs Eric W. Biederman
2013-01-22  9:13   ` [PATCH 03/11] Implement commonio_append Eric W. Biederman
2013-01-22  9:13   ` Eric W. Biederman
2013-01-22  9:14   ` Eric W. Biederman [this message]
     [not found]     ` <87liblr344.fsf-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>
2013-01-23 18:22       ` [PATCH 04/11] Add backend support for suboridnate uids and gids Serge E. Hallyn
     [not found]         ` <20130123182206.GA4468-7LNsyQBKDXoIagZqoN9o3w@public.gmane.org>
2013-01-24 22:42           ` Eric W. Biederman
     [not found]             ` <87a9ryyzh2.fsf-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>
2013-01-24 22:50               ` Serge Hallyn
2013-01-24 22:59                 ` Eric W. Biederman
2013-01-24 23:13                 ` [PATCH] subordinateio: Fix subordinate_parse to have an internal static buffer Eric W. Biederman
2013-01-22  9:15   ` [PATCH 05/11] Implement find_new_sub_uids find_new_sub_gids Eric W. Biederman
2013-01-22  9:16   ` [PATCH 06/11] userdel: Add support for removing subordinate user and group ids Eric W. Biederman
2013-01-22  9:17   ` [PATCH 07/11] useradd: Add support for subordinate user identifiers Eric W. Biederman
2013-01-22  9:17   ` [PATCH 08/11] Add support for detecting busy subordinate user ids Eric W. Biederman
2013-01-22  9:18   ` [PATCH 09/11] usermod: Add support for subordinate uids and gids Eric W. Biederman
2013-01-22  9:19   ` [PATCH 10/11] newusers: Add support for assiging " Eric W. Biederman
2013-01-22  9:20   ` [PATCH 11/11] newuidmap, newgidmap: New suid helpers for using " Eric W. Biederman
     [not found]     ` <87ehhdpoag.fsf-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>
2013-02-04 18:31       ` [PATCH 11/11] newuidmap,newgidmap: " Serge E. Hallyn
     [not found]         ` <20130204183129.GA27179-7LNsyQBKDXoIagZqoN9o3w@public.gmane.org>
2013-02-05 17:20           ` Serge E. Hallyn
2013-02-06  0:28           ` [PATCH 11/11] newuidmap, newgidmap: " Eric W. Biederman
     [not found]             ` <87sj5ai8us.fsf-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>
2013-02-06  3:00               ` [PATCH 11/11] newuidmap,newgidmap: " Serge E. Hallyn
     [not found]       ` <87fw1tr33a.fsf-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>
2013-06-15  0:15         ` [PATCH 05/11] Implement find_new_sub_uids find_new_sub_gids Seth Arnold
2013-10-25 20:30       ` [PATCH 11/11] newuidmap,newgidmap: New suid helpers for using subordinate uids and gids Serge E. Hallyn
     [not found]         ` <20131025203025.GA2467-7LNsyQBKDXoIagZqoN9o3w@public.gmane.org>
2013-10-26  0:42           ` [PATCH 11/11] newuidmap, newgidmap: " Eric W. Biederman
     [not found]             ` <87zjpw278b.fsf-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>
2013-10-26  2:33               ` Serge Hallyn
2013-10-26 21:50                 ` Eric W. Biederman
     [not found]                   ` <87iowjya4j.fsf-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>
2013-10-27 23:53                     ` Serge E. Hallyn
2013-01-29 18:15   ` [PATCH 00/11] pkg-shadow support subordinate ids with user namespaces Rob Landley
2013-01-29 22:28     ` Eric W. Biederman
2013-01-30  5:35   ` Vasily Kulikov
2013-01-30  6:40     ` Eric W. Biederman
     [not found]       ` <87vcafyy0k.fsf-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>
2013-01-30  7:38         ` Vasily Kulikov
2013-02-22 12:16   ` Glauber Costa
     [not found]     ` <51276189.5040803-bzQdu9zFT3WakBO8gow8eQ@public.gmane.org>
2013-02-22 16:34       ` Eric W. Biederman
     [not found]         ` <87zjyw489z.fsf-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>
2013-02-22 17:09           ` Glauber Costa
     [not found]             ` <5127A657.3010909-bzQdu9zFT3WakBO8gow8eQ@public.gmane.org>
2013-02-25 14:34               ` Serge Hallyn
     [not found]             ` <20130225143451.GE4387@sergelap>
2013-02-25 14:38               ` Glauber Costa
     [not found]                 ` <512B7773.9060704-bzQdu9zFT3WakBO8gow8eQ@public.gmane.org>
2013-02-25 15:15                   ` Serge Hallyn
2013-02-26  1:03                   ` Eric W. Biederman
2013-02-25 14:30           ` Serge Hallyn
2013-03-03 15:37   ` Serge E. Hallyn
2013-03-07 15:23   ` Dwight Engen
2013-07-28 17:14   ` [Pkg-shadow-devel] " Christian PERRIER
     [not found]     ` <20130728171451.GX5670-FvNwPcshoeM/MCprI7ZU+I/wHUNs+SP4HZ5vskTnxNA@public.gmane.org>
2013-07-28 17:58       ` Eric W. Biederman
     [not found]         ` <87r4eilg6y.fsf-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>
2013-07-29  0:33           ` Serge Hallyn
     [not found]         ` <11218395-363e-46cd-b7a1-4488079a4986@email.android.com>
     [not found]           ` <11218395-363e-46cd-b7a1-4488079a4986-2ueSQiBKiTY7tOexoI0I+QC/G2K4zDHf@public.gmane.org>
2013-08-06 14:54             ` Serge E. Hallyn
     [not found]               ` <20130806145403.GA20913-7LNsyQBKDXoIagZqoN9o3w@public.gmane.org>
2013-08-06 22:53                 ` Nicolas François
     [not found]                   ` <20130806225332.GA14109-pDMkYksm/NDBVznEOA0nCqMXiC8k1aZu0e7PPNI6Mm0@public.gmane.org>
2013-08-07 15:33                     ` Serge Hallyn
2013-08-07 18:04                       ` Eric W. Biederman
     [not found]                         ` <87eha5peb8.fsf-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>
2013-08-09 18:40                           ` Nicolas François
     [not found] ` <20130303153726.GA14737@austin.hallyn.com>
     [not found]   ` <20130303153726.GA14737-anj0Drq5vpzx6HRWoRZK3AC/G2K4zDHf@public.gmane.org>
2013-03-04  5:56     ` Christian PERRIER
     [not found]   ` <20130304055654.GE2629@mykerinos.kheops.frmug.org>
     [not found]     ` <20130304055654.GE2629-FvNwPcshoeM/MCprI7ZU+I/wHUNs+SP4HZ5vskTnxNA@public.gmane.org>
2013-03-05 22:05       ` Serge E. Hallyn
     [not found] ` <20130307102352.4a5943cd@oracle.com>
     [not found]   ` <20130307102352.4a5943cd-QHcLZuEGTsvQT0dZR+AlfA@public.gmane.org>
2013-03-07 21:54     ` Serge E. Hallyn
     [not found]       ` <20130307215457.GB9348-anj0Drq5vpzx6HRWoRZK3AC/G2K4zDHf@public.gmane.org>
2013-03-07 22:56         ` Eric W. Biederman
     [not found]           ` <876212rf9b.fsf-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>
2013-03-08  6:50             ` [Pkg-shadow-devel] " Christian PERRIER
     [not found]               ` <20130308065019.GI5885-FvNwPcshoeM/MCprI7ZU+I/wHUNs+SP4HZ5vskTnxNA@public.gmane.org>
2013-06-02 13:48                 ` Serge E. Hallyn
     [not found]                   ` <20130602134823.GB8004-anj0Drq5vpzx6HRWoRZK3AC/G2K4zDHf@public.gmane.org>
2013-06-02 14:04                     ` Christian PERRIER
     [not found]                       ` <20130602140436.GK9152-FvNwPcshoeM/MCprI7ZU+I/wHUNs+SP4HZ5vskTnxNA@public.gmane.org>
2013-06-02 14:33                         ` Serge E. Hallyn

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87liblr344.fsf@xmission.com \
    --to=ebiederm-as9lmozglivwk0htik3j/w@public.gmane.org \
    --cc=Pkg-shadow-devel-XbBxUvOt3X2LieD7tvxI8l/i77bcL1HB@public.gmane.org \
    --cc=containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org \
    --cc=mtk.manpages-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
    --cc=nicolas.francois-Fa7rcPG4DJn7nK0/Xc0eeg@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.