~ubuntu-branches/ubuntu/trusty/shadow/trusty-updates

« back to all changes in this revision

Viewing changes to debian/patches/userns/11_userns_newxidmap

  • Committer: Package Import Robot
  • Author(s): Dmitrijs Ledkovs, Serge Hallyn
  • Date: 2013-06-28 11:31:51 UTC
  • Revision ID: package-import@ubuntu.com-20130628113151-9uapv6rwwj08whr7
Tags: 1:4.1.5.1-1ubuntu5
[ Serge Hallyn ]
* debian/patches/userns: patches from Eric Biederman to enable use of
  subuids, plus some bugfix patches on top of them. (LP: #1192864)
* passwd.install: add new manpages
* debian/control, debian/uidmap.install: create new uidmap package
  containing the new setuid-root binaries newuidmap and newgidmap 
* debian/subuid, debian/rules: install a default /etc/subuid and /etc/subgid
* debian/patches/userns/16_add-argument-sanity-checking.patch: address
  three sanity checking concerns brought up by sarnold at
  http://lists.alioth.debian.org/pipermail/pkg-shadow-devel/2013-June/ \
  009752.html.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
From ebiederm@xmission.com  Tue Jan 22 09:22:07 2013
 
2
Return-Path: <ebiederm@xmission.com>
 
3
X-Original-To: serge@hallyn.com
 
4
Delivered-To: serge@hallyn.com
 
5
Received: by mail.hallyn.com (Postfix, from userid 5001)
 
6
        id E5D16C80F4; Tue, 22 Jan 2013 09:22:07 +0000 (UTC)
 
7
X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail
 
8
X-Spam-Level: 
 
9
X-Spam-Status: No, score=-0.2 required=8.0 tests=BAD_ENC_HEADER,BAYES_00,
 
10
        LONGWORDS,RCVD_IN_DNSWL_MED autolearn=no version=3.3.1
 
11
Received: from out02.mta.xmission.com (out02.mta.xmission.com [166.70.13.232])
 
12
        (using TLSv1 with cipher AES256-SHA (256/256 bits))
 
13
        (No client certificate requested)
 
14
        by mail.hallyn.com (Postfix) with ESMTPS id 2E206C80D1
 
15
        for <serge@hallyn.com>; Tue, 22 Jan 2013 09:22:03 +0000 (UTC)
 
16
Received: from in02.mta.xmission.com ([166.70.13.52])
 
17
        by out02.mta.xmission.com with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32)
 
18
        (Exim 4.76)
 
19
        (envelope-from <ebiederm@xmission.com>)
 
20
        id 1Txa1k-0000xE-Ix; Tue, 22 Jan 2013 02:20:20 -0700
 
21
Received: from c-98-207-153-68.hsd1.ca.comcast.net ([98.207.153.68] helo=eric-ThinkPad-X220.xmission.com)
 
22
        by in02.mta.xmission.com with esmtpsa (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16)
 
23
        (Exim 4.76)
 
24
        (envelope-from <ebiederm@xmission.com>)
 
25
        id 1Txa1b-00059T-Lu; Tue, 22 Jan 2013 02:20:20 -0700
 
26
From: ebiederm@xmission.com (Eric W. Biederman)
 
27
To: Nicolas =?utf-8?Q?Fran=C3=A7ois?= <nicolas.francois@centraliens.net>
 
28
Cc: <Pkg-shadow-devel@lists.alioth.debian.org>,  Linux Containers <containers@lists.linux-foundation.org>,  "Michael Kerrisk \(man-pages\)" <mtk.manpages@gmail.com>,  "Serge E. Hallyn" <serge@hallyn.com>
 
29
References: <87d2wxshu0.fsf@xmission.com>
 
30
Date: Tue, 22 Jan 2013 01:20:07 -0800
 
31
In-Reply-To: <87d2wxshu0.fsf@xmission.com> (Eric W. Biederman's message of
 
32
        "Tue, 22 Jan 2013 01:11:19 -0800")
 
33
Message-ID: <87ehhdpoag.fsf@xmission.com>
 
34
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.1 (gnu/linux)
 
35
MIME-Version: 1.0
 
36
Content-Type: text/plain
 
37
X-XM-AID: U2FsdGVkX1/nox3f5bDq7zL9eOiGra/HoCkv7o07HDs=
 
38
X-SA-Exim-Connect-IP: 98.207.153.68
 
39
X-SA-Exim-Mail-From: ebiederm@xmission.com
 
40
Subject: [PATCH 11/11] newuidmap,newgidmap: New suid helpers for using subordinate uids and gids
 
41
X-SA-Exim-Version: 4.2.1 (built Wed, 14 Nov 2012 14:26:46 -0700)
 
42
X-SA-Exim-Scanned: Yes (on in02.mta.xmission.com)
 
43
X-UID: 2081                                                  
 
44
Status: RO
 
45
Content-Length: 31344
 
46
Lines: 965
 
47
 
 
48
 
 
49
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
 
50
---
 
51
 libmisc/Makefile.am |    2 +
 
52
 libmisc/idmapping.c |  126 +++++++++++++++++++++++++++++++++++
 
53
 libmisc/idmapping.h |   44 ++++++++++++
 
54
 man/Makefile.am     |    4 +
 
55
 man/newgidmap.1.xml |  157 +++++++++++++++++++++++++++++++++++++++++++
 
56
 man/newuidmap.1.xml |  154 +++++++++++++++++++++++++++++++++++++++++++
 
57
 src/Makefile.am     |    5 +-
 
58
 src/newgidmap.c     |  183 +++++++++++++++++++++++++++++++++++++++++++++++++++
 
59
 src/newuidmap.c     |  183 +++++++++++++++++++++++++++++++++++++++++++++++++++
 
60
 9 files changed, 856 insertions(+), 2 deletions(-)
 
61
 create mode 100644 libmisc/idmapping.c
 
62
 create mode 100644 libmisc/idmapping.h
 
63
 create mode 100644 man/newgidmap.1.xml
 
64
 create mode 100644 man/newuidmap.1.xml
 
65
 create mode 100644 src/newgidmap.c
 
66
 create mode 100644 src/newuidmap.c
 
67
 
 
68
Index: shadow/libmisc/Makefile.am
 
69
===================================================================
 
70
--- shadow.orig/libmisc/Makefile.am     2013-02-01 15:27:53.836080342 -0600
 
71
+++ shadow/libmisc/Makefile.am  2013-02-01 15:27:53.828080343 -0600
 
72
@@ -32,6 +32,8 @@
 
73
        getgr_nam_gid.c \
 
74
        getrange.c \
 
75
        hushed.c \
 
76
+       idmapping.h \
 
77
+       idmapping.c \
 
78
        isexpired.c \
 
79
        limits.c \
 
80
        list.c log.c \
 
81
Index: shadow/libmisc/idmapping.c
 
82
===================================================================
 
83
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
 
84
+++ shadow/libmisc/idmapping.c  2013-02-01 15:27:53.828080343 -0600
 
85
@@ -0,0 +1,126 @@
 
86
+/*
 
87
+ * Copyright (c) 2013 Eric Biederman
 
88
+ * All rights reserved.
 
89
+ *
 
90
+ * Redistribution and use in source and binary forms, with or without
 
91
+ * modification, are permitted provided that the following conditions
 
92
+ * are met:
 
93
+ * 1. Redistributions of source code must retain the above copyright
 
94
+ *    notice, this list of conditions and the following disclaimer.
 
95
+ * 2. Redistributions in binary form must reproduce the above copyright
 
96
+ *    notice, this list of conditions and the following disclaimer in the
 
97
+ *    documentation and/or other materials provided with the distribution.
 
98
+ * 3. The name of the copyright holders or contributors may not be used to
 
99
+ *    endorse or promote products derived from this software without
 
100
+ *    specific prior written permission.
 
101
+ *
 
102
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
103
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
104
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 
105
+ * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
 
106
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
107
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 
108
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
109
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
110
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
111
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
112
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
113
+ */
 
114
+
 
115
+#include <config.h>
 
116
+#include <sys/types.h>
 
117
+#include <sys/stat.h>
 
118
+#include <fcntl.h>
 
119
+#include <limits.h>
 
120
+#include <stdlib.h>
 
121
+#include "prototypes.h"
 
122
+#include "idmapping.h"
 
123
+
 
124
+struct map_range *get_map_ranges(int ranges, int argc, char **argv)
 
125
+{
 
126
+       struct map_range *mappings, *mapping;
 
127
+       int idx, argidx;
 
128
+
 
129
+       if ((ranges * 3) > argc) {
 
130
+               fprintf(stderr, "ranges: %u argc: %d\n",
 
131
+                       ranges, argc);
 
132
+               fprintf(stderr,
 
133
+                       _( "%s: Not enough arguments to form %u mappings\n"),
 
134
+                       Prog, ranges);
 
135
+               return NULL;
 
136
+       }
 
137
+
 
138
+       mappings = calloc(ranges, sizeof(*mappings));
 
139
+       if (!mappings) {
 
140
+               fprintf(stderr, _( "%s: Memory allocation failure\n"),
 
141
+                       Prog);
 
142
+               exit(EXIT_FAILURE);
 
143
+       }
 
144
+
 
145
+       /* Gather up the ranges from the command line */
 
146
+       mapping = mappings;
 
147
+       for (idx = 0; idx < ranges; idx++, argidx += 3, mapping++) {
 
148
+               if (!getulong(argv[argidx + 0], &mapping->upper))
 
149
+                       return NULL;
 
150
+               if (!getulong(argv[argidx + 1], &mapping->lower))
 
151
+                       return NULL;
 
152
+               if (!getulong(argv[argidx + 2], &mapping->count))
 
153
+                       return NULL;
 
154
+       }
 
155
+       return mappings;
 
156
+}
 
157
+
 
158
+/* Number of ascii digits needed to print any unsigned long in decimal.
 
159
+ * There are approximately 10 bits for every 3 decimal digits.
 
160
+ * So from bits to digits the formula is roundup((Number of bits)/10) * 3.
 
161
+ * For common sizes of integers this works out to:
 
162
+ *  2bytes -->  6 ascii estimate  -> 65536  (5 real)
 
163
+ *  4bytes --> 12 ascii estimated -> 4294967296 (10 real)
 
164
+ *  8bytes --> 21 ascii estimated -> 18446744073709551616 (20 real)
 
165
+ * 16bytes --> 39 ascii estimated -> 340282366920938463463374607431768211456 (39 real)
 
166
+ */
 
167
+#define ULONG_DIGITS ((((sizeof(unsigned long) * CHAR_BIT) + 9)/10)*3)
 
168
+
 
169
+
 
170
+void write_mapping(int proc_dir_fd, int ranges, struct map_range *mappings,
 
171
+       const char *map_file)
 
172
+{
 
173
+       int idx;
 
174
+       struct map_range *mapping;
 
175
+       size_t bufsize;
 
176
+       char *buf, *pos;
 
177
+       int fd;
 
178
+
 
179
+       bufsize = ranges * ((ULONG_DIGITS  + 1) * 3);
 
180
+       pos = buf = xmalloc(bufsize);
 
181
+
 
182
+       /* Build the mapping command */
 
183
+       mapping = mappings;
 
184
+       for (idx = 0; idx < ranges; idx++, mapping++) {
 
185
+               /* Append this range to the string that will be written */
 
186
+               int written = snprintf(pos, bufsize - (pos - buf),
 
187
+                       "%lu %lu %lu\n",
 
188
+                       mapping->upper,
 
189
+                       mapping->lower,
 
190
+                       mapping->count);
 
191
+               if ((written <= 0) || (written >= (bufsize - (pos - buf)))) {
 
192
+                       fprintf(stderr, _("%s: snprintf failed!\n"), Prog);
 
193
+                       exit(EXIT_FAILURE);
 
194
+               }
 
195
+               pos += written;
 
196
+       }
 
197
+
 
198
+       /* Write the mapping to the maping file */
 
199
+       fd = openat(proc_dir_fd, map_file, O_WRONLY);
 
200
+       if (fd < 0) {
 
201
+               fprintf(stderr, _("%s: open of %s failed: %s\n"),
 
202
+                       Prog, map_file, strerror(errno));
 
203
+               exit(EXIT_FAILURE);
 
204
+       }
 
205
+       if (write(fd, buf, pos - buf) != (pos - buf)) {
 
206
+               fprintf(stderr, _("%s: write to %s failed: %s\n"),
 
207
+                       Prog, map_file, strerror(errno));
 
208
+               exit(EXIT_FAILURE);
 
209
+       }
 
210
+       close(fd);
 
211
+}
 
212
Index: shadow/libmisc/idmapping.h
 
213
===================================================================
 
214
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
 
215
+++ shadow/libmisc/idmapping.h  2013-02-01 15:27:53.828080343 -0600
 
216
@@ -0,0 +1,44 @@
 
217
+/*
 
218
+ * Copyright (c) 2013 Eric Biederman
 
219
+ * All rights reserved.
 
220
+ *
 
221
+ * Redistribution and use in source and binary forms, with or without
 
222
+ * modification, are permitted provided that the following conditions
 
223
+ * are met:
 
224
+ * 1. Redistributions of source code must retain the above copyright
 
225
+ *    notice, this list of conditions and the following disclaimer.
 
226
+ * 2. Redistributions in binary form must reproduce the above copyright
 
227
+ *    notice, this list of conditions and the following disclaimer in the
 
228
+ *    documentation and/or other materials provided with the distribution.
 
229
+ * 3. The name of the copyright holders or contributors may not be used to
 
230
+ *    endorse or promote products derived from this software without
 
231
+ *    specific prior written permission.
 
232
+ *
 
233
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
234
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
235
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 
236
+ * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
 
237
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
238
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 
239
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
240
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
241
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
242
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
243
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
244
+ */
 
245
+
 
246
+#ifndef _IDMAPPING_H_
 
247
+#define _IDMAPPING_H_
 
248
+
 
249
+struct map_range {
 
250
+       unsigned long upper;
 
251
+       unsigned long lower;
 
252
+       unsigned long count;
 
253
+};
 
254
+
 
255
+extern struct map_range *get_map_ranges(int ranges, int argc, char **argv);
 
256
+extern void write_mapping(int proc_dir_fd, int ranges,
 
257
+       struct map_range *mappings, const char *map_file);
 
258
+
 
259
+#endif /* _ID_MAPPING_H_ */
 
260
+
 
261
Index: shadow/man/Makefile.am
 
262
===================================================================
 
263
--- shadow.orig/man/Makefile.am 2013-02-01 15:27:53.836080342 -0600
 
264
+++ shadow/man/Makefile.am      2013-02-01 15:27:53.828080343 -0600
 
265
@@ -30,7 +30,9 @@
 
266
        man1/login.1 \
 
267
        man5/login.defs.5 \
 
268
        man8/logoutd.8 \
 
269
+       man1/newgidmap.1 \
 
270
        man1/newgrp.1 \
 
271
+       man1/newuidmap.1 \
 
272
        man8/newusers.8 \
 
273
        man8/nologin.8 \
 
274
        man1/passwd.1 \
 
275
@@ -83,7 +85,9 @@
 
276
        login.access.5.xml \
 
277
        login.defs.5.xml \
 
278
        logoutd.8.xml \
 
279
+       newgidmap.1.xml \
 
280
        newgrp.1.xml \
 
281
+       newuidmap.1.xml \
 
282
        newusers.8.xml \
 
283
        nologin.8.xml \
 
284
        passwd.1.xml \
 
285
Index: shadow/man/newgidmap.1.xml
 
286
===================================================================
 
287
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
 
288
+++ shadow/man/newgidmap.1.xml  2013-02-01 15:27:53.828080343 -0600
 
289
@@ -0,0 +1,157 @@
 
290
+<?xml version="1.0" encoding="UTF-8"?>
 
291
+<!--
 
292
+   Copyright (c) 2013 Eric W. Biederman
 
293
+   All rights reserved.
 
294
+  
 
295
+   Redistribution and use in source and binary forms, with or without
 
296
+   modification, are permitted provided that the following conditions
 
297
+   are met:
 
298
+   1. Redistributions of source code must retain the above copyright
 
299
+      notice, this list of conditions and the following disclaimer.
 
300
+   2. Redistributions in binary form must reproduce the above copyright
 
301
+      notice, this list of conditions and the following disclaimer in the
 
302
+      documentation and/or other materials provided with the distribution.
 
303
+   3. The name of the copyright holders or contributors may not be used to
 
304
+      endorse or promote products derived from this software without
 
305
+      specific prior written permission.
 
306
+  
 
307
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
308
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
309
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 
310
+   PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
 
311
+   HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
312
+   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 
313
+   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
314
+   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
315
+   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
316
+   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
317
+   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
318
+-->
 
319
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook V4.5//EN"
 
320
+  "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
 
321
+<!-- SHADOW-CONFIG-HERE -->
 
322
+]>
 
323
+
 
324
+<refentry id='newgidmap.1'>
 
325
+  <refmeta>
 
326
+    <refentrytitle>newgidmap</refentrytitle>
 
327
+    <manvolnum>1</manvolnum>
 
328
+    <refmiscinfo class="sectdesc">User Commands</refmiscinfo>
 
329
+    <refmiscinfo class="source">shadow-utils</refmiscinfo>
 
330
+    <refmiscinfo class="version">&SHADOW_UTILS_VERSION;</refmiscinfo>
 
331
+  </refmeta>
 
332
+  <refnamediv id='name'>
 
333
+    <refname>newgidmap</refname>
 
334
+    <refpurpose>set the gid mapping of a user namespace</refpurpose>
 
335
+  </refnamediv>
 
336
+
 
337
+  <refsynopsisdiv id='synopsis'>
 
338
+    <cmdsynopsis>
 
339
+      <command>newgidmap</command>
 
340
+      <arg choice='plain'>
 
341
+       <replaceable>pid</replaceable>
 
342
+      </arg>
 
343
+      <arg choice='plain'>
 
344
+       <replaceable>gid</replaceable>
 
345
+      </arg>
 
346
+      <arg choice='plain'>
 
347
+       <replaceable>lowergid</replaceable>
 
348
+      </arg>
 
349
+      <arg choice='plain'>
 
350
+       <replaceable>count</replaceable>
 
351
+      </arg>
 
352
+      <arg choice='opt'>
 
353
+       <arg choice='plain'>
 
354
+         <replaceable>pid</replaceable>
 
355
+       </arg>
 
356
+       <arg choice='plain'>
 
357
+         <replaceable>gid</replaceable>
 
358
+       </arg>
 
359
+       <arg choice='plain'>
 
360
+         <replaceable>lowergid</replaceable>
 
361
+       </arg>
 
362
+       <arg choice='plain'>
 
363
+         <replaceable>count</replaceable>
 
364
+       </arg>
 
365
+       <arg choice='opt'>
 
366
+         <replaceable>...</replaceable>
 
367
+       </arg>
 
368
+      </arg>
 
369
+    </cmdsynopsis>
 
370
+  </refsynopsisdiv>
 
371
+
 
372
+  <refsect1 id='description'>
 
373
+    <title>DESCRIPTION</title>
 
374
+    <para>
 
375
+      The <command>newgidmap</command> sets <filename>/proc/[pid]/gid_map</filename> based on it's
 
376
+      command line arguments and the gids allowed in <filename>/etc/subgid</filename>.
 
377
+    </para>
 
378
+
 
379
+  </refsect1>
 
380
+
 
381
+  <refsect1 id='options'>
 
382
+    <title>OPTIONS</title>
 
383
+    <para>
 
384
+      There currently are no options to the <command>newgidmap</command> command.
 
385
+    </para>
 
386
+    <variablelist remap='IP'>
 
387
+    </variablelist>
 
388
+  </refsect1>
 
389
+
 
390
+  <refsect1 id='note'>
 
391
+    <title>NOTE</title>
 
392
+    <para>
 
393
+      The only restriction placed on the login shell is that the command
 
394
+      name must be listed in <filename>/etc/shells</filename>, unless the
 
395
+      invoker is the superuser, and then any value may be added. An
 
396
+      account with a restricted login shell may not change her login shell.
 
397
+      For this reason, placing <filename>/bin/rsh</filename> in
 
398
+      <filename>/etc/shells</filename> is discouraged since accidentally
 
399
+      changing to a restricted shell would prevent the user from ever
 
400
+      changing her login shell back to its original value.
 
401
+    </para>
 
402
+  </refsect1>
 
403
+
 
404
+
 
405
+  <refsect1 id='files'>
 
406
+    <title>FILES</title>
 
407
+    <variablelist>
 
408
+      <varlistentry>
 
409
+       <term><filename>/etc/subgid</filename></term>
 
410
+       <listitem>
 
411
+         <para>List of users subordinate user IDs.</para>
 
412
+       </listitem>
 
413
+      </varlistentry>
 
414
+      <varlistentry>
 
415
+       <term><filename>/proc/[pid]/gid_map</filename></term>
 
416
+       <listitem>
 
417
+         <para>Mapping of gids from one between user namespaces.</para>
 
418
+       </listitem>
 
419
+      </varlistentry>
 
420
+    </variablelist>
 
421
+  </refsect1>
 
422
+
 
423
+  <refsect1 id='see_also'>
 
424
+    <title>SEE ALSO</title>
 
425
+    <para>
 
426
+      <citerefentry>
 
427
+       <refentrytitle>login.defs</refentrytitle><manvolnum>5</manvolnum>
 
428
+      </citerefentry>,
 
429
+      <citerefentry>
 
430
+       <refentrytitle>useradd</refentrytitle><manvolnum>8</manvolnum>
 
431
+      </citerefentry>,
 
432
+      <citerefentry>
 
433
+       <refentrytitle>usermod</refentrytitle><manvolnum>8</manvolnum>
 
434
+      </citerefentry>,
 
435
+      <citerefentry>
 
436
+       <refentrytitle>newusers</refentrytitle><manvolnum>8</manvolnum>
 
437
+      </citerefentry>,
 
438
+      <citerefentry>
 
439
+       <refentrytitle>userdel</refentrytitle><manvolnum>8</manvolnum>
 
440
+      </citerefentry>,
 
441
+      <citerefentry>
 
442
+       <refentrytitle>subgid</refentrytitle><manvolnum>5</manvolnum>
 
443
+      </citerefentry>.
 
444
+    </para>
 
445
+  </refsect1>
 
446
+</refentry>
 
447
Index: shadow/man/newuidmap.1.xml
 
448
===================================================================
 
449
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
 
450
+++ shadow/man/newuidmap.1.xml  2013-02-01 15:27:53.828080343 -0600
 
451
@@ -0,0 +1,154 @@
 
452
+<?xml version="1.0" encoding="UTF-8"?>
 
453
+<!--
 
454
+   Copyright (c) 2013 Eric W. Biederman
 
455
+   All rights reserved.
 
456
+  
 
457
+   Redistribution and use in source and binary forms, with or without
 
458
+   modification, are permitted provided that the following conditions
 
459
+   are met:
 
460
+   1. Redistributions of source code must retain the above copyright
 
461
+      notice, this list of conditions and the following disclaimer.
 
462
+   2. Redistributions in binary form must reproduce the above copyright
 
463
+      notice, this list of conditions and the following disclaimer in the
 
464
+      documentation and/or other materials provided with the distribution.
 
465
+   3. The name of the copyright holders or contributors may not be used to
 
466
+      endorse or promote products derived from this software without
 
467
+      specific prior written permission.
 
468
+  
 
469
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
470
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
471
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 
472
+   PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
 
473
+   HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
474
+   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 
475
+   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
476
+   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
477
+   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
478
+   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
479
+   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
480
+-->
 
481
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook V4.5//EN"
 
482
+  "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
 
483
+<!-- SHADOW-CONFIG-HERE -->
 
484
+]>
 
485
+
 
486
+<refentry id='newuidmap.1'>
 
487
+  <refmeta>
 
488
+    <refentrytitle>newuidmap</refentrytitle>
 
489
+    <manvolnum>1</manvolnum>
 
490
+    <refmiscinfo class="sectdesc">User Commands</refmiscinfo>
 
491
+    <refmiscinfo class="source">shadow-utils</refmiscinfo>
 
492
+    <refmiscinfo class="version">&SHADOW_UTILS_VERSION;</refmiscinfo>
 
493
+  </refmeta>
 
494
+  <refnamediv id='name'>
 
495
+    <refname>newuidmap</refname>
 
496
+    <refpurpose>set the uid mapping of a user namespace</refpurpose>
 
497
+  </refnamediv>
 
498
+
 
499
+  <refsynopsisdiv id='synopsis'>
 
500
+    <cmdsynopsis>
 
501
+      <command>newuidmap</command>
 
502
+      <arg choice='plain'>
 
503
+       <replaceable>pid</replaceable>
 
504
+      </arg>
 
505
+      <arg choice='plain'>
 
506
+       <replaceable>uid</replaceable>
 
507
+      </arg>
 
508
+      <arg choice='plain'>
 
509
+       <replaceable>loweruid</replaceable>
 
510
+      </arg>
 
511
+      <arg choice='plain'>
 
512
+       <replaceable>count</replaceable>
 
513
+      </arg>
 
514
+      <arg choice='opt'>
 
515
+       <arg choice='plain'>
 
516
+         <replaceable>uid</replaceable>
 
517
+       </arg>
 
518
+       <arg choice='plain'>
 
519
+         <replaceable>loweruid</replaceable>
 
520
+       </arg>
 
521
+       <arg choice='plain'>
 
522
+         <replaceable>count</replaceable>
 
523
+       </arg>
 
524
+       <arg choice='opt'>
 
525
+         <replaceable>...</replaceable>
 
526
+       </arg>
 
527
+      </arg>
 
528
+    </cmdsynopsis>
 
529
+  </refsynopsisdiv>
 
530
+
 
531
+  <refsect1 id='description'>
 
532
+    <title>DESCRIPTION</title>
 
533
+    <para>
 
534
+      The <command>newuidmap</command> sets <filename>/proc/[pid]/uid_map</filename> based on it's
 
535
+      command line arguments and the uids allowed in <filename>/etc/subuid</filename>.
 
536
+    </para>
 
537
+
 
538
+  </refsect1>
 
539
+
 
540
+  <refsect1 id='options'>
 
541
+    <title>OPTIONS</title>
 
542
+    <para>
 
543
+      There currently are no options to the <command>newuidmap</command> command.
 
544
+    </para>
 
545
+    <variablelist remap='IP'>
 
546
+    </variablelist>
 
547
+  </refsect1>
 
548
+
 
549
+  <refsect1 id='note'>
 
550
+    <title>NOTE</title>
 
551
+    <para>
 
552
+      The only restriction placed on the login shell is that the command
 
553
+      name must be listed in <filename>/etc/shells</filename>, unless the
 
554
+      invoker is the superuser, and then any value may be added. An
 
555
+      account with a restricted login shell may not change her login shell.
 
556
+      For this reason, placing <filename>/bin/rsh</filename> in
 
557
+      <filename>/etc/shells</filename> is discouraged since accidentally
 
558
+      changing to a restricted shell would prevent the user from ever
 
559
+      changing her login shell back to its original value.
 
560
+    </para>
 
561
+  </refsect1>
 
562
+
 
563
+
 
564
+  <refsect1 id='files'>
 
565
+    <title>FILES</title>
 
566
+    <variablelist>
 
567
+      <varlistentry>
 
568
+       <term><filename>/etc/subuid</filename></term>
 
569
+       <listitem>
 
570
+         <para>List of users subordinate user IDs.</para>
 
571
+       </listitem>
 
572
+      </varlistentry>
 
573
+      <varlistentry>
 
574
+       <term><filename>/proc/[pid]/uid_map</filename></term>
 
575
+       <listitem>
 
576
+         <para>Mapping of uids from one between user namespaces.</para>
 
577
+       </listitem>
 
578
+      </varlistentry>
 
579
+    </variablelist>
 
580
+  </refsect1>
 
581
+
 
582
+  <refsect1 id='see_also'>
 
583
+    <title>SEE ALSO</title>
 
584
+    <para>
 
585
+      <citerefentry>
 
586
+       <refentrytitle>login.defs</refentrytitle><manvolnum>5</manvolnum>
 
587
+      </citerefentry>,
 
588
+      <citerefentry>
 
589
+       <refentrytitle>useradd</refentrytitle><manvolnum>8</manvolnum>
 
590
+      </citerefentry>,
 
591
+      <citerefentry>
 
592
+       <refentrytitle>usermod</refentrytitle><manvolnum>8</manvolnum>
 
593
+      </citerefentry>,
 
594
+      <citerefentry>
 
595
+       <refentrytitle>newusers</refentrytitle><manvolnum>8</manvolnum>
 
596
+      </citerefentry>,
 
597
+      <citerefentry>
 
598
+       <refentrytitle>userdel</refentrytitle><manvolnum>8</manvolnum>
 
599
+      </citerefentry>,
 
600
+      <citerefentry>
 
601
+       <refentrytitle>subuid</refentrytitle><manvolnum>5</manvolnum>
 
602
+      </citerefentry>.
 
603
+    </para>
 
604
+  </refsect1>
 
605
+</refentry>
 
606
Index: shadow/src/Makefile.am
 
607
===================================================================
 
608
--- shadow.orig/src/Makefile.am 2013-02-01 15:27:53.836080342 -0600
 
609
+++ shadow/src/Makefile.am      2013-02-01 15:27:53.832080342 -0600
 
610
@@ -23,7 +23,8 @@
 
611
 # $prefix/bin and $prefix/sbin, no install-data hacks...)
 
612
 
 
613
 bin_PROGRAMS   = groups login su
 
614
-ubin_PROGRAMS  = faillog lastlog chage chfn chsh expiry gpasswd newgrp passwd
 
615
+ubin_PROGRAMS  = faillog lastlog chage chfn chsh expiry gpasswd newgrp passwd \
 
616
+       newgidmap newuidmap
 
617
 usbin_PROGRAMS = \
 
618
        cppw \
 
619
        chgpasswd \
 
620
@@ -50,7 +51,7 @@
 
621
 noinst_PROGRAMS = id sulogin
 
622
 
 
623
 suidbins       = su
 
624
-suidubins      = chage chfn chsh expiry gpasswd newgrp passwd
 
625
+suidubins      = chage chfn chsh expiry gpasswd newgrp passwd newuidmap newgidmap
 
626
 if ACCT_TOOLS_SETUID
 
627
        suidubins += chage chgpasswd chpasswd groupadd groupdel groupmod newusers useradd userdel usermod
 
628
 endif
 
629
Index: shadow/src/newgidmap.c
 
630
===================================================================
 
631
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
 
632
+++ shadow/src/newgidmap.c      2013-02-01 15:27:53.832080342 -0600
 
633
@@ -0,0 +1,183 @@
 
634
+/*
 
635
+ * Copyright (c) 2013 Eric Biederman
 
636
+ * All rights reserved.
 
637
+ *
 
638
+ * Redistribution and use in source and binary forms, with or without
 
639
+ * modification, are permitted provided that the following conditions
 
640
+ * are met:
 
641
+ * 1. Redistributions of source code must retain the above copyright
 
642
+ *    notice, this list of conditions and the following disclaimer.
 
643
+ * 2. Redistributions in binary form must reproduce the above copyright
 
644
+ *    notice, this list of conditions and the following disclaimer in the
 
645
+ *    documentation and/or other materials provided with the distribution.
 
646
+ * 3. The name of the copyright holders or contributors may not be used to
 
647
+ *    endorse or promote products derived from this software without
 
648
+ *    specific prior written permission.
 
649
+ *
 
650
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
651
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
652
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 
653
+ * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
 
654
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
655
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 
656
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
657
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
658
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
659
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
660
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
661
+ */
 
662
+
 
663
+#include <config.h>
 
664
+#include <stdio.h>
 
665
+#include <string.h>
 
666
+#include <errno.h>
 
667
+#include <stdbool.h>
 
668
+#include <stdlib.h>
 
669
+#include <sys/types.h>
 
670
+#include <sys/stat.h>
 
671
+#include <fcntl.h>
 
672
+#include "defines.h"
 
673
+#include "prototypes.h"
 
674
+#include "subordinateio.h"
 
675
+#include "idmapping.h"
 
676
+
 
677
+/*
 
678
+ * Global variables
 
679
+ */
 
680
+const char *Prog;
 
681
+
 
682
+static bool verify_range(struct passwd *pw, struct map_range *range)
 
683
+{
 
684
+       /* An empty range is invalid */
 
685
+       if (range->count == 0)
 
686
+               return false;
 
687
+
 
688
+       /* Test /etc/subgid */
 
689
+       if (have_sub_gids(pw->pw_name, range->lower, range->count))
 
690
+               return true;
 
691
+
 
692
+       /* Allow a process to map it's own gid */
 
693
+       if ((range->count == 1) && (pw->pw_gid == range->lower))
 
694
+               return true;
 
695
+
 
696
+       return false;
 
697
+}
 
698
+
 
699
+static void verify_ranges(struct passwd *pw, int ranges,
 
700
+       struct map_range *mappings)
 
701
+{
 
702
+       struct map_range *mapping;
 
703
+       int idx;
 
704
+
 
705
+       mapping = mappings;
 
706
+       for (idx = 0; idx < ranges; idx++, mapping++) {
 
707
+               if (!verify_range(pw, mapping)) {
 
708
+                       fprintf(stderr, _( "%s: gid range [%lu-%lu) -> [%lu-%lu) not allowed\n"),
 
709
+                               Prog,
 
710
+                               mapping->upper,
 
711
+                               mapping->upper + mapping->count,
 
712
+                               mapping->lower,
 
713
+                               mapping->lower + mapping->count);
 
714
+                       exit(EXIT_FAILURE);
 
715
+               }
 
716
+       }
 
717
+}
 
718
+
 
719
+static void usage(void)
 
720
+{
 
721
+       fprintf(stderr, _("usage: %s <pid> <gid> <lowergid> <count> [ <gid> <lowergid> <count> ] ... \n"), Prog);
 
722
+       exit(EXIT_FAILURE);
 
723
+}
 
724
+
 
725
+/*
 
726
+ * newgidmap - Set the gid_map for the specified process
 
727
+ */
 
728
+int main(int argc, char **argv)
 
729
+{
 
730
+       char proc_dir_name[PATH_MAX];
 
731
+       char *target_str;
 
732
+       pid_t target, parent;
 
733
+       int proc_dir_fd;
 
734
+       int ranges;
 
735
+       struct map_range *mappings;
 
736
+       struct stat st;
 
737
+       struct passwd *pw;
 
738
+       int written;
 
739
+
 
740
+       Prog = Basename (argv[0]);
 
741
+
 
742
+       /*
 
743
+        * The valid syntax are
 
744
+        * newgidmap target_pid
 
745
+        */
 
746
+       if (argc < 2)
 
747
+               usage();
 
748
+
 
749
+       /* Find the process that needs it's user namespace
 
750
+        * gid mapping set.
 
751
+        */
 
752
+       target_str = argv[1];
 
753
+       if (!get_pid(target_str, &target))
 
754
+               usage();
 
755
+
 
756
+       written = snprintf(proc_dir_name, sizeof(proc_dir_name), "/proc/%u/",
 
757
+               target);
 
758
+       if ((written <= 0) || (written >= sizeof(proc_dir_name))) {
 
759
+               fprintf(stderr, "%s: snprintf of proc path failed: %s\n",
 
760
+                       Prog, strerror(errno));
 
761
+       }
 
762
+
 
763
+       proc_dir_fd = open(proc_dir_name, O_DIRECTORY);
 
764
+       if (proc_dir_fd < 0) {
 
765
+               fprintf(stderr, _("%s: Could not open proc directory for target %u\n"),
 
766
+                       Prog, target);
 
767
+               return EXIT_FAILURE;
 
768
+       }
 
769
+
 
770
+       /* Who am i? */
 
771
+       pw = get_my_pwent ();
 
772
+       if (NULL == pw) {
 
773
+               fprintf (stderr,
 
774
+                       _("%s: Cannot determine your user name.\n"),
 
775
+                       Prog);
 
776
+               SYSLOG ((LOG_WARN, "Cannot determine the user name of the caller (UID %lu)",
 
777
+                               (unsigned long) getuid ()));
 
778
+               return EXIT_FAILURE;
 
779
+       }
 
780
+       
 
781
+       /* Get the effective uid and effective gid of the target process */
 
782
+       if (fstat(proc_dir_fd, &st) < 0) {
 
783
+               fprintf(stderr, _("%s: Could not stat directory for target %u\n"),
 
784
+                       Prog, target);
 
785
+               return EXIT_FAILURE;
 
786
+       }
 
787
+
 
788
+       /* Verify real user and real group matches the password entry
 
789
+        * and the effective user and group of the program whose
 
790
+        * mappings we have been asked to set.
 
791
+        */
 
792
+       if ((getuid() != pw->pw_uid) ||
 
793
+           (getgid() != pw->pw_gid) ||
 
794
+           (pw->pw_uid != st.st_uid) ||
 
795
+           (pw->pw_gid != st.st_gid)) {
 
796
+               fprintf(stderr, _( "%s: Target %u is owned by a different user\n" ),
 
797
+                       Prog, target);
 
798
+               return EXIT_FAILURE;
 
799
+       }
 
800
+
 
801
+       if (!sub_gid_open(O_RDONLY)) {
 
802
+               return EXIT_FAILURE;
 
803
+       }
 
804
+
 
805
+       ranges = ((argc - 2) + 2) / 3;
 
806
+       mappings = get_map_ranges(ranges, argc - 2, argv + 2);
 
807
+       if (!mappings)
 
808
+               usage();
 
809
+
 
810
+       verify_ranges(pw, ranges, mappings);
 
811
+
 
812
+       write_mapping(proc_dir_fd, ranges, mappings, "gid_map");
 
813
+       sub_gid_close();
 
814
+
 
815
+       return EXIT_SUCCESS;
 
816
+}
 
817
Index: shadow/src/newuidmap.c
 
818
===================================================================
 
819
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
 
820
+++ shadow/src/newuidmap.c      2013-02-01 15:27:53.832080342 -0600
 
821
@@ -0,0 +1,183 @@
 
822
+/*
 
823
+ * Copyright (c) 2013 Eric Biederman
 
824
+ * All rights reserved.
 
825
+ *
 
826
+ * Redistribution and use in source and binary forms, with or without
 
827
+ * modification, are permitted provided that the following conditions
 
828
+ * are met:
 
829
+ * 1. Redistributions of source code must retain the above copyright
 
830
+ *    notice, this list of conditions and the following disclaimer.
 
831
+ * 2. Redistributions in binary form must reproduce the above copyright
 
832
+ *    notice, this list of conditions and the following disclaimer in the
 
833
+ *    documentation and/or other materials provided with the distribution.
 
834
+ * 3. The name of the copyright holders or contributors may not be used to
 
835
+ *    endorse or promote products derived from this software without
 
836
+ *    specific prior written permission.
 
837
+ *
 
838
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
839
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
840
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 
841
+ * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
 
842
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
843
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 
844
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
845
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
846
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
847
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
848
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
849
+ */
 
850
+
 
851
+#include <config.h>
 
852
+#include <stdio.h>
 
853
+#include <string.h>
 
854
+#include <errno.h>
 
855
+#include <stdbool.h>
 
856
+#include <stdlib.h>
 
857
+#include <sys/types.h>
 
858
+#include <sys/stat.h>
 
859
+#include <fcntl.h>
 
860
+#include "defines.h"
 
861
+#include "prototypes.h"
 
862
+#include "subordinateio.h"
 
863
+#include "idmapping.h"
 
864
+
 
865
+/*
 
866
+ * Global variables
 
867
+ */
 
868
+const char *Prog;
 
869
+
 
870
+static bool verify_range(struct passwd *pw, struct map_range *range)
 
871
+{
 
872
+       /* An empty range is invalid */
 
873
+       if (range->count == 0)
 
874
+               return false;
 
875
+
 
876
+       /* Test /etc/subuid */
 
877
+       if (have_sub_uids(pw->pw_name, range->lower, range->count))
 
878
+               return true;
 
879
+
 
880
+       /* Allow a process to map it's own uid */
 
881
+       if ((range->count == 1) && (pw->pw_uid == range->lower))
 
882
+               return true;
 
883
+
 
884
+       return false;
 
885
+}
 
886
+
 
887
+static void verify_ranges(struct passwd *pw, int ranges,
 
888
+       struct map_range *mappings)
 
889
+{
 
890
+       struct map_range *mapping;
 
891
+       int idx;
 
892
+
 
893
+       mapping = mappings;
 
894
+       for (idx = 0; idx < ranges; idx++, mapping++) {
 
895
+               if (!verify_range(pw, mapping)) {
 
896
+                       fprintf(stderr, _( "%s: uid range [%lu-%lu) -> [%lu-%lu) not allowed\n"),
 
897
+                               Prog,
 
898
+                               mapping->upper,
 
899
+                               mapping->upper + mapping->count,
 
900
+                               mapping->lower,
 
901
+                               mapping->lower + mapping->count);
 
902
+                       exit(EXIT_FAILURE);
 
903
+               }
 
904
+       }
 
905
+}
 
906
+
 
907
+void usage(void)
 
908
+{
 
909
+       fprintf(stderr, _("usage: %s <pid> <uid> <loweruid> <count> [ <uid> <loweruid> <count> ] ... \n"), Prog);
 
910
+       exit(EXIT_FAILURE);
 
911
+}
 
912
+
 
913
+/*
 
914
+ * newuidmap - Set the uid_map for the specified process
 
915
+ */
 
916
+int main(int argc, char **argv)
 
917
+{
 
918
+       char proc_dir_name[PATH_MAX];
 
919
+       char *target_str;
 
920
+       pid_t target, parent;
 
921
+       int proc_dir_fd;
 
922
+       int ranges;
 
923
+       struct map_range *mappings;
 
924
+       struct stat st;
 
925
+       struct passwd *pw;
 
926
+       int written;
 
927
+
 
928
+       Prog = Basename (argv[0]);
 
929
+
 
930
+       /*
 
931
+        * The valid syntax are
 
932
+        * newuidmap target_pid
 
933
+        */
 
934
+       if (argc < 2)
 
935
+               usage();
 
936
+
 
937
+       /* Find the process that needs it's user namespace
 
938
+        * uid mapping set.
 
939
+        */
 
940
+       target_str = argv[1];
 
941
+       if (!get_pid(target_str, &target))
 
942
+               usage();
 
943
+
 
944
+       written = snprintf(proc_dir_name, sizeof(proc_dir_name), "/proc/%u/",
 
945
+               target);
 
946
+       if ((written <= 0) || (written >= sizeof(proc_dir_name))) {
 
947
+               fprintf(stderr, "%s: snprintf of proc path failed: %s\n",
 
948
+                       Prog, strerror(errno));
 
949
+       }
 
950
+
 
951
+       proc_dir_fd = open(proc_dir_name, O_DIRECTORY);
 
952
+       if (proc_dir_fd < 0) {
 
953
+               fprintf(stderr, _("%s: Could not open proc directory for target %u\n"),
 
954
+                       Prog, target);
 
955
+               return EXIT_FAILURE;
 
956
+       }
 
957
+
 
958
+       /* Who am i? */
 
959
+       pw = get_my_pwent ();
 
960
+       if (NULL == pw) {
 
961
+               fprintf (stderr,
 
962
+                       _("%s: Cannot determine your user name.\n"),
 
963
+                       Prog);
 
964
+               SYSLOG ((LOG_WARN, "Cannot determine the user name of the caller (UID %lu)",
 
965
+                               (unsigned long) getuid ()));
 
966
+               return EXIT_FAILURE;
 
967
+       }
 
968
+       
 
969
+       /* Get the effective uid and effective gid of the target process */
 
970
+       if (fstat(proc_dir_fd, &st) < 0) {
 
971
+               fprintf(stderr, _("%s: Could not stat directory for target %u\n"),
 
972
+                       Prog, target);
 
973
+               return EXIT_FAILURE;
 
974
+       }
 
975
+
 
976
+       /* Verify real user and real group matches the password entry
 
977
+        * and the effective user and group of the program whose
 
978
+        * mappings we have been asked to set.
 
979
+        */
 
980
+       if ((getuid() != pw->pw_uid) ||
 
981
+           (getgid() != pw->pw_gid) ||
 
982
+           (pw->pw_uid != st.st_uid) ||
 
983
+           (pw->pw_gid != st.st_gid)) {
 
984
+               fprintf(stderr, _( "%s: Target %u is owned by a different user\n" ),
 
985
+                       Prog, target);
 
986
+               return EXIT_FAILURE;
 
987
+       }
 
988
+
 
989
+       if (!sub_uid_open(O_RDONLY)) {
 
990
+               return EXIT_FAILURE;
 
991
+       }
 
992
+
 
993
+       ranges = ((argc - 2) + 2) / 3;
 
994
+       mappings = get_map_ranges(ranges, argc - 2, argv + 2);
 
995
+       if (!mappings)
 
996
+               usage();
 
997
+
 
998
+       verify_ranges(pw, ranges, mappings);
 
999
+
 
1000
+       write_mapping(proc_dir_fd, ranges, mappings, "uid_map");
 
1001
+       sub_uid_close();
 
1002
+
 
1003
+       return EXIT_SUCCESS;
 
1004
+}