Re: [PATCH v3 3/4] nsenter: new applet

2016-03-14 Thread Mike Frysinger
On 14 Mar 2016 16:15, Rich Felker wrote:
> On Mon, Mar 14, 2016 at 02:27:56PM -0400, Mike Frysinger wrote:
> > On 14 Mar 2016 18:11, Bartosz Gołaszewski wrote:
> > > 2016-03-14 15:27 GMT+01:00 Mike Frysinger :
> > > > On 14 Mar 2016 11:07, Bartosz Golaszewski wrote:
> > > >> +#ifndef __BB_NAMESPACE_H
> > > >> +#define __BB_NAMESPACE_H
> > > >
> > > > use a naming style like other busybox headers
> > > >
> > > >> +/*
> > > >> + * Longest possible path to a procfs file used in namespace utils. 
> > > >> Must be
> > > >> + * able to contain the '/proc/' string, the '/ns/user' string which 
> > > >> is the
> > > >> + * longest namespace name and a 32-bit integer representing the 
> > > >> process ID.
> > > >> + */
> > > >> +#define NS_PROC_PATH_MAX (sizeof("/proc//ns/user") + sizeof(pid_t) * 
> > > >> 3)
> > > >
> > > > using the sizeof pid_t as a proxy for how many chars it'd take to render
> > > > a decimal number in ASCII is wonky.  just hardcode it as "10" since that
> > > > is the largest unsigned 32bit number ("4294967296").
> > > 
> > > Can you elaborate on how it's wonky? While your solution is perfectly
> > > fine I think that there's nothing wrong with the way I've done it
> > > neither.
> > 
> > the code seems to assume that the byte size scales into the number of
> > chars required to represent the number in base 10 when it's really a
> > log scale.  here's a table to show it's wonky:
> 
> sizeof is already a log scale. 3*sizeof(pid_t) is
> 3*log_256(MAX_PID+1), which is greater than 3*ceil(log_1000(MAX_PID)),
> the actual space requirement.

i was referring to log base 10 which is normally what log() represents.

the concern isn't with the limits that Linux happens to impose by default
(0x8000) but with making sure bad values don't screw everything up.  just
because the linux kernel doesn't normally create a pid larger than 32k at
the moment doesn't mean bad values can't leak in somewhere else.  these
pid #'s are being sourced directly from the user.

> > pid_t |sizeof |*3 val|actual|
> > size  |(bytes)|(char)|  |
> > (bits)|   |  |  |
> > --|---|--|--|
> >   8   |  1|  3   |  4   |
> >  16   |  2|  6   |  6   |
> >  32   |  4| 12   | 11   |
> >  64   |  8| 24   | 20   |
> > 128   | 16| 48   | 40   |
> > 
> > the "actual" value is one higher than you might expect because pid_t
> > is a signed quantity.  for 8bit, "-128" is 0x80 and takes 4 bytes.
> > for 32bit ("int"), "-2147483648" is 0x8000 and takes 11 bytes.
> 
> While pid_t is signed, negative values are not meaningful as pids;
> they're pgids or special sentinels in some contexts. If this code is
> trying to print a negative pid into a pathname used in /proc, that's a
> bug. But in general, when using the 3*sizeof idiom you should add +1
> for a sign if needed and another +1 for null termination if not
> already included elsewhere.

relying on full error checking all the time is a bad way to design
string buffers.  "this func will smash the stack if you happen to
pass in a negative value" is terrible.

the NUL byte is technicallly already counted when you do the
sizeof("/proc/...").

but this esoteric logic is why i'm pushing for something better than
sprinkling ad-hoc logic everywhere and hoping for the best.
-mike


signature.asc
Description: Digital signature
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox

Re: [PATCH v3 3/4] nsenter: new applet

2016-03-14 Thread Rich Felker
On Mon, Mar 14, 2016 at 02:27:56PM -0400, Mike Frysinger wrote:
> On 14 Mar 2016 18:11, Bartosz Gołaszewski wrote:
> > 2016-03-14 15:27 GMT+01:00 Mike Frysinger :
> > > On 14 Mar 2016 11:07, Bartosz Golaszewski wrote:
> > >> +#ifndef __BB_NAMESPACE_H
> > >> +#define __BB_NAMESPACE_H
> > >
> > > use a naming style like other busybox headers
> > >
> > >> +/*
> > >> + * Longest possible path to a procfs file used in namespace utils. Must 
> > >> be
> > >> + * able to contain the '/proc/' string, the '/ns/user' string which is 
> > >> the
> > >> + * longest namespace name and a 32-bit integer representing the process 
> > >> ID.
> > >> + */
> > >> +#define NS_PROC_PATH_MAX (sizeof("/proc//ns/user") + sizeof(pid_t) * 3)
> > >
> > > using the sizeof pid_t as a proxy for how many chars it'd take to render
> > > a decimal number in ASCII is wonky.  just hardcode it as "10" since that
> > > is the largest unsigned 32bit number ("4294967296").
> > 
> > Can you elaborate on how it's wonky? While your solution is perfectly
> > fine I think that there's nothing wrong with the way I've done it
> > neither.
> 
> the code seems to assume that the byte size scales into the number of
> chars required to represent the number in base 10 when it's really a
> log scale.  here's a table to show it's wonky:

sizeof is already a log scale. 3*sizeof(pid_t) is
3*log_256(MAX_PID+1), which is greater than 3*ceil(log_1000(MAX_PID)),
the actual space requirement.

> pid_t |sizeof |*3 val|actual|
> size  |(bytes)|(char)|  |
> (bits)|   |  |  |
> --|---|--|--|
>   8   |  1|  3   |  4   |
>  16   |  2|  6   |  6   |
>  32   |  4| 12   | 11   |
>  64   |  8| 24   | 20   |
> 128   | 16| 48   | 40   |
> 
> the "actual" value is one higher than you might expect because pid_t
> is a signed quantity.  for 8bit, "-128" is 0x80 and takes 4 bytes.
> for 32bit ("int"), "-2147483648" is 0x8000 and takes 11 bytes.

While pid_t is signed, negative values are not meaningful as pids;
they're pgids or special sentinels in some contexts. If this code is
trying to print a negative pid into a pathname used in /proc, that's a
bug. But in general, when using the 3*sizeof idiom you should add +1
for a sign if needed and another +1 for null termination if not
already included elsewhere.

Rich
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox

Re: [PATCH v3 3/4] nsenter: new applet

2016-03-14 Thread Rich Felker
On Mon, Mar 14, 2016 at 10:27:19AM -0400, Mike Frysinger wrote:
> On 14 Mar 2016 11:07, Bartosz Golaszewski wrote:
> > +#ifndef __BB_NAMESPACE_H
> > +#define __BB_NAMESPACE_H
> 
> use a naming style like other busybox headers

And in particular, don't use leading underscores, ever. They're not
available for use by applications.

> > +/*
> > + * Longest possible path to a procfs file used in namespace utils. Must be
> > + * able to contain the '/proc/' string, the '/ns/user' string which is the
> > + * longest namespace name and a 32-bit integer representing the process ID.
> > + */
> > +#define NS_PROC_PATH_MAX (sizeof("/proc//ns/user") + sizeof(pid_t) * 3)
> 
> using the sizeof pid_t as a proxy for how many chars it'd take to render
> a decimal number in ASCII is wonky.  just hardcode it as "10" since that
> is the largest unsigned 32bit number ("4294967296").

I disagree that this is "wonky". It's a simple safe bound for number
of characters needed to print an integer type. Hard-coding a number,
while unlikely to affect any future Linux targets, is a bomb in the
code that could become dangerous if someone reused it on a system with
pid_t larger than 32-bit.

Rich
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: [PATCH v3 3/4] nsenter: new applet

2016-03-14 Thread Michael Conrad

On 3/14/2016 2:27 PM, Mike Frysinger wrote:

the code seems to assume that the byte size scales into the number of
chars required to represent the number in base 10 when it's really a
log scale.  here's a table to show it's wonky:


The number of bytes is also a log scale.  The ratio of log_256 to log_10 
is 2.4, so 3 is a reasonable approximation.  It reasonably handles the 
case of 16-bit, 32-bit and 64-bit PIDs (which are all I would think 
would ever appear in the wild)


I don't see what the complaint is since its only bytes of stack space 
anyway...

___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: [PATCH v3 3/4] nsenter: new applet

2016-03-14 Thread Mike Frysinger
On 14 Mar 2016 14:27, Mike Frysinger wrote:
> On 14 Mar 2016 18:11, Bartosz Gołaszewski wrote:
> > 2016-03-14 15:27 GMT+01:00 Mike Frysinger :
> > > On 14 Mar 2016 11:07, Bartosz Golaszewski wrote:
> > >> +#ifndef __BB_NAMESPACE_H
> > >> +#define __BB_NAMESPACE_H
> > >
> > > use a naming style like other busybox headers
> > >
> > >> +/*
> > >> + * Longest possible path to a procfs file used in namespace utils. Must 
> > >> be
> > >> + * able to contain the '/proc/' string, the '/ns/user' string which is 
> > >> the
> > >> + * longest namespace name and a 32-bit integer representing the process 
> > >> ID.
> > >> + */
> > >> +#define NS_PROC_PATH_MAX (sizeof("/proc//ns/user") + sizeof(pid_t) * 3)
> > >
> > > using the sizeof pid_t as a proxy for how many chars it'd take to render
> > > a decimal number in ASCII is wonky.  just hardcode it as "10" since that
> > > is the largest unsigned 32bit number ("4294967296").
> > 
> > Can you elaborate on how it's wonky? While your solution is perfectly
> > fine I think that there's nothing wrong with the way I've done it
> > neither.
> 
> the code seems to assume that the byte size scales into the number of
> chars required to represent the number in base 10 when it's really a
> log scale.  here's a table to show it's wonky:
> 
> pid_t |sizeof |*3 val|actual|
> size  |(bytes)|(char)|  |
> (bits)|   |  |  |
> --|---|--|--|
>   8   |  1|  3   |  4   |
>  16   |  2|  6   |  6   |
>  32   |  4| 12   | 11   |
>  64   |  8| 24   | 20   |
> 128   | 16| 48   | 40   |
> 
> the "actual" value is one higher than you might expect because pid_t
> is a signed quantity.  for 8bit, "-128" is 0x80 and takes 4 bytes.
> for 32bit ("int"), "-2147483648" is 0x8000 and takes 11 bytes.
> 
> so my initial suggestion of "10" should actually be "11".

just to be extra clear: i'm not saying your current code produces wrong
behavior using current code/systems -- when pid_t is a 32-bit signed int,
then the padding of 12 bytes is sufficient.  i'm saying the code as is is
written now implies a relationship that does not actually exist.

all that said, i'm sure there is code in busybox already that writes it
this way and would blow up horribly if pid_t was not a 32-bit signed int.
perhaps adding some proc helpers wouldn't be a terrible idea ?
-mike


signature.asc
Description: Digital signature
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox

Re: [PATCH v3 3/4] nsenter: new applet

2016-03-14 Thread Mike Frysinger
On 14 Mar 2016 18:11, Bartosz Gołaszewski wrote:
> 2016-03-14 15:27 GMT+01:00 Mike Frysinger :
> > On 14 Mar 2016 11:07, Bartosz Golaszewski wrote:
> >> +#ifndef __BB_NAMESPACE_H
> >> +#define __BB_NAMESPACE_H
> >
> > use a naming style like other busybox headers
> >
> >> +/*
> >> + * Longest possible path to a procfs file used in namespace utils. Must be
> >> + * able to contain the '/proc/' string, the '/ns/user' string which is the
> >> + * longest namespace name and a 32-bit integer representing the process 
> >> ID.
> >> + */
> >> +#define NS_PROC_PATH_MAX (sizeof("/proc//ns/user") + sizeof(pid_t) * 3)
> >
> > using the sizeof pid_t as a proxy for how many chars it'd take to render
> > a decimal number in ASCII is wonky.  just hardcode it as "10" since that
> > is the largest unsigned 32bit number ("4294967296").
> 
> Can you elaborate on how it's wonky? While your solution is perfectly
> fine I think that there's nothing wrong with the way I've done it
> neither.

the code seems to assume that the byte size scales into the number of
chars required to represent the number in base 10 when it's really a
log scale.  here's a table to show it's wonky:

pid_t |sizeof |*3 val|actual|
size  |(bytes)|(char)|  |
(bits)|   |  |  |
--|---|--|--|
  8   |  1|  3   |  4   |
 16   |  2|  6   |  6   |
 32   |  4| 12   | 11   |
 64   |  8| 24   | 20   |
128   | 16| 48   | 40   |

the "actual" value is one higher than you might expect because pid_t
is a signed quantity.  for 8bit, "-128" is 0x80 and takes 4 bytes.
for 32bit ("int"), "-2147483648" is 0x8000 and takes 11 bytes.

so my initial suggestion of "10" should actually be "11".
-mike


signature.asc
Description: Digital signature
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox

Re: [PATCH v3 3/4] nsenter: new applet

2016-03-14 Thread Bartosz Gołaszewski
2016-03-14 15:27 GMT+01:00 Mike Frysinger :
> On 14 Mar 2016 11:07, Bartosz Golaszewski wrote:
>> +#ifndef __BB_NAMESPACE_H
>> +#define __BB_NAMESPACE_H
>
> use a naming style like other busybox headers
>
>> +/*
>> + * Longest possible path to a procfs file used in namespace utils. Must be
>> + * able to contain the '/proc/' string, the '/ns/user' string which is the
>> + * longest namespace name and a 32-bit integer representing the process ID.
>> + */
>> +#define NS_PROC_PATH_MAX (sizeof("/proc//ns/user") + sizeof(pid_t) * 3)
>
> using the sizeof pid_t as a proxy for how many chars it'd take to render
> a decimal number in ASCII is wonky.  just hardcode it as "10" since that
> is the largest unsigned 32bit number ("4294967296").
>

Can you elaborate on how it's wonky? While your solution is perfectly
fine I think that there's nothing wrong with the way I've done it
neither.

>> + status = setgid(gid);
>> + if (status < 0)
>> + bb_perror_msg_and_die("setgid failed");
>
> use xsetgid
>

Done in v4.

>> + status = setuid(uid);
>> + if (status < 0)
>> + bb_perror_msg_and_die("setuid failed");
>
> use xsetuid

Done in v4.

-- 
Best regards,
Bartosz Golaszewski
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: [PATCH v2 2/4] unshare: new applet

2016-03-14 Thread Bartosz Gołaszewski
2016-03-14 15:11 GMT+01:00 Mike Frysinger :
> On 14 Mar 2016 11:08, Bartosz Gołaszewski wrote:
>> 2016-03-11 18:24 GMT+01:00 Mike Frysinger :
>> > On 11 Mar 2016 18:10, Bartosz Golaszewski wrote:
>> >> +int unshare_main(int argc UNUSED_PARAM, char **argv)
>> >> +{
>> >> + static struct namespace ns_list[] = {
>> >
>> > const ?
>> >
>>
>> Nope, we're using char *path to store the mount points.
>
> that's kind of a big chunk of data to blend read-only & writable
> data in.  can't you create a parallel array just for the writable
> data and use the indices you have now to index it ?
> -mike

Please take a look at v4. I also tried making struct namespace_descr
common for both applets but with the option bits that have different
values and need manual assignment it turned out the code actually got
bigger, so I dropped it.

-- 
Best regards,
Bartosz Golaszewski
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox

[PATCH v4 4/4] namespace utils: code shrink

2016-03-14 Thread Bartosz Golaszewski
Both unshare and nsenter use similar code to fork and have the parent
wait for child's completion. Move it to a common library function.

function old new   delta
continue_as_child  - 105+105
unshare_main10661004 -62
nsenter_main 850 753 -97
--
(add/remove: 2/0 grow/shrink: 0/2 up/down: 105/-159)  Total: -54 bytes
   textdata bss dec hex filename
 82955244869120  843158   cdd96 busybox_old
 82949844869120  843104   cdd60 busybox_unstripped

Signed-off-by: Bartosz Golaszewski 
---
 util-linux/namespace.c | 34 ++
 util-linux/namespace.h |  7 +++
 util-linux/nsenter.c   | 20 ++--
 util-linux/unshare.c   | 19 ++-
 4 files changed, 45 insertions(+), 35 deletions(-)
 create mode 100644 util-linux/namespace.c

diff --git a/util-linux/namespace.c b/util-linux/namespace.c
new file mode 100644
index 000..1cfa1ae
--- /dev/null
+++ b/util-linux/namespace.c
@@ -0,0 +1,34 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Common namespace code.
+ *
+ * Copyright (C) 2016 by Bartosz Golaszewski 
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
+ */
+
+//kbuild:lib-$(CONFIG_UNSHARE) += namespace.o
+//kbuild:lib-$(CONFIG_NSENTER) += namespace.o
+
+#include "libbb.h"
+#include "namespace.h"
+
+void continue_as_child(void)
+{
+   int exit_status, rv;
+   pid_t pid;
+
+   pid = xfork();
+   if (pid > 0) {
+   rv = safe_waitpid(pid, &exit_status, WUNTRACED);
+   if (rv < 0)
+   bb_perror_msg_and_die("waitpid");
+
+   if (WIFEXITED(exit_status))
+   exit(WEXITSTATUS(exit_status));
+   else if (WIFSIGNALED(exit_status))
+   kill(getpid(), WTERMSIG(exit_status));
+
+   bb_error_msg_and_die("child exit failed");
+   } /* Child continues. */
+}
diff --git a/util-linux/namespace.h b/util-linux/namespace.h
index da79fd9..42e8361 100644
--- a/util-linux/namespace.h
+++ b/util-linux/namespace.h
@@ -17,4 +17,11 @@
  */
 #define NS_PROC_PATH_MAX (sizeof("/proc//ns/user") + sizeof(pid_t) * 3)
 
+/*
+ * Fork and wait for the child process to finish. Exit with the child process'
+ * exit status or deliver the signal which killed the child to the parent.
+ * Exit if fork() or waitpid() fails.
+ */
+void continue_as_child(void);
+
 #endif /* __BB_NAMESPACE_H */
diff --git a/util-linux/nsenter.c b/util-linux/nsenter.c
index cdf5b79..fc7e88e 100644
--- a/util-linux/nsenter.c
+++ b/util-linux/nsenter.c
@@ -328,24 +328,8 @@ int nsenter_main(int argc UNUSED_PARAM, char **argv)
 * Entering the pid namespace implies forking unless it's been
 * explicitly requested by the user not to.
 */
-   if (!(opts & OPT_nofork) && (opts & OPT_pid)) {
-   int exit_status;
-   pid_t pid;
-
-   pid = xfork();
-   if (pid > 0) {
-   status = safe_waitpid(pid, &exit_status, 0);
-   if (status < 0)
-   bb_perror_msg_and_die("waitpid");
-
-   if (WIFEXITED(exit_status))
-   return WEXITSTATUS(exit_status);
-   else if (WIFSIGNALED(exit_status))
-   kill(getpid(), WTERMSIG(exit_status));
-
-   bb_error_msg_and_die("child exit failed");
-   } /* Child continues. */
-   }
+   if (!(opts & OPT_nofork) && (opts & OPT_pid))
+   continue_as_child();
 
if (opts & OPT_setgid) {
status = setgroups(0, NULL);
diff --git a/util-linux/unshare.c b/util-linux/unshare.c
index c1811be..6cefd81 100644
--- a/util-linux/unshare.c
+++ b/util-linux/unshare.c
@@ -397,23 +397,8 @@ int unshare_main(int argc UNUSED_PARAM, char **argv)
 * child. The user may want to use this option to spawn a new process
 * that'll become PID 1 in this new namespace.
 */
-   if (opts & OPT_fork) {
-   int exit_status;
-
-   pid = xfork();
-   if (pid > 0) {
-   status = safe_waitpid(pid, &exit_status, 0);
-   if (status < 0)
-   bb_perror_msg_and_die("waitpid");
-
-   if (WIFEXITED(exit_status))
-   return WEXITSTATUS(exit_status);
-   else if (WIFSIGNALED(exit_status))
-   kill(getpid(), WTERMSIG(exit_status));
-
-   bb_error_msg_and_die("child exit failed");
-   } /* Child continues. */
-   }
+   if (opts & OPT_fork)

[PATCH v4 0/4] util-linux: namespace utils

2016-03-14 Thread Bartosz Golaszewski
This series adds two namespaces-related applets reimplementing most
arguments supported by their upstream util-linux counterparts.

The fourth patch is an optional code shrink.

v4:
- split the namespace structure into the read-only and modifiable
  parts
- made the read-only definition const and moved it out of the main
  function in both applets
- moved the position indicators to an enum and replaced all the
  ARRAY_SIZE() macros with NS_COUNT constant defined there
- fixed some whitespace errors

v3:
- moved the namespace positions into an enum for better readability

v2:
- v1 was badly rebased and patch 3/4 didn't compile - fixed it
- added some parenthesis for better readability in patch 3/4

v1: http://lists.busybox.net/pipermail/busybox/2016-March/083957.html

Bartosz Golaszewski (4):
  libbb: add BIT() macro
  unshare: new applet
  nsenter: new applet
  namespace utils: code shrink

 include/libbb.h|   2 +
 util-linux/namespace.c |  34 
 util-linux/namespace.h |  27 +++
 util-linux/nsenter.c   | 351 +++
 util-linux/unshare.c   | 443 +
 5 files changed, 857 insertions(+)
 create mode 100644 util-linux/namespace.c
 create mode 100644 util-linux/namespace.h
 create mode 100644 util-linux/nsenter.c
 create mode 100644 util-linux/unshare.c

-- 
2.1.4

___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


[PATCH v4 3/4] nsenter: new applet

2016-03-14 Thread Bartosz Golaszewski
Implement a fully featured (sans selinux part) nsenter applet.

Signed-off-by: Bartosz Golaszewski 
---
 util-linux/namespace.h |  20 +++
 util-linux/nsenter.c   | 367 +
 util-linux/unshare.c   |  12 +-
 3 files changed, 390 insertions(+), 9 deletions(-)
 create mode 100644 util-linux/namespace.h
 create mode 100644 util-linux/nsenter.c

diff --git a/util-linux/namespace.h b/util-linux/namespace.h
new file mode 100644
index 000..da79fd9
--- /dev/null
+++ b/util-linux/namespace.h
@@ -0,0 +1,20 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Common namespace code.
+ *
+ * Copyright (C) 2016 by Bartosz Golaszewski 
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
+ */
+
+#ifndef __BB_NAMESPACE_H
+#define __BB_NAMESPACE_H
+
+/*
+ * Longest possible path to a procfs file used in namespace utils. Must be
+ * able to contain the '/proc/' string, the '/ns/user' string which is the
+ * longest namespace name and a 32-bit integer representing the process ID.
+ */
+#define NS_PROC_PATH_MAX (sizeof("/proc//ns/user") + sizeof(pid_t) * 3)
+
+#endif /* __BB_NAMESPACE_H */
diff --git a/util-linux/nsenter.c b/util-linux/nsenter.c
new file mode 100644
index 000..cdf5b79
--- /dev/null
+++ b/util-linux/nsenter.c
@@ -0,0 +1,367 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini nsenter implementation for busybox.
+ *
+ * Copyright (C) 2016 by Bartosz Golaszewski 
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
+ */
+
+//config:config NSENTER
+//config:  bool "nsenter"
+//config:  default y
+//config:  select PLATFORM_LINUX
+//config:  help
+//config:Run program with namespaces of other processes.
+//config:
+//config:config FEATURE_NSENTER_LONG_OPTS
+//config:  bool "enable long options"
+//config:  default y
+//config:  depends on NSENTER && LONG_OPTS
+//config:  help
+//config:Support long options for the nsenter applet. This makes
+//config:the busybox implementation more compatible with upstream.
+
+//applet:IF_NSENTER(APPLET(nsenter, BB_DIR_USR_BIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_NSENTER) += nsenter.o
+
+//usage:#define nsenter_trivial_usage
+//usage:   "[options]  [args...]"
+//usage:#if ENABLE_FEATURE_NSENTER_LONG_OPTS
+//usage:#define nsenter_full_usage "\n\n"
+//usage:   "Options:"
+//usage: "\n   -t, --target   target process to get 
namespaces from"
+//usage: "\n   -m, --mount[=]enter mount namespace"
+//usage: "\n   -u, --uts[=]  enter UTS namespace 
(hostname etc)"
+//usage: "\n   -i, --ipc[=]  enter System V IPC 
namespace"
+//usage: "\n   -n, --net[=]  enter network namespace"
+//usage: "\n   -p, --pid[=]  enter pid namespace"
+//usage: "\n   -U, --user[=] enter user namespace"
+//usage: "\n   -S, --setuid   set uid in entered 
namespace"
+//usage: "\n   -G, --setgid   set gid in entered 
namespace"
+//usage: "\n   -P, --preserve-credentials  do not touch uids or 
gids"
+//usage: "\n   -r, --root[=]  set the root directory"
+//usage: "\n   -w, --wd[=]set the working 
directory"
+//usage: "\n   -F, --no-fork   do not fork before 
exec'ing "
+//usage:#else
+//usage:#define nsenter_full_usage "\n\n"
+//usage:   "Options:"
+//usage: "\n   -t target process to get namespaces from"
+//usage: "\n   -m [] enter mount namespace"
+//usage: "\n   -u [] enter UTS namespace (hostname etc)"
+//usage: "\n   -i [] enter System V IPC namespace"
+//usage: "\n   -n [] enter network namespace"
+//usage: "\n   -p [] enter pid namespace"
+//usage: "\n   -U [] enter user namespace"
+//usage: "\n   -S set uid in entered namespace"
+//usage: "\n   -G set gid in entered namespace"
+//usage: "\n   -P  do not touch uids or gids"
+//usage: "\n   -r []  set the root directory"
+//usage: "\n   -w []  set the working directory"
+//usage: "\n   -F  do not fork before exec'ing "
+//usage:#endif
+
+#include "libbb.h"
+#include "namespace.h"
+
+#include 
+
+enum {
+   OPT_target  = BIT( 0),
+   OPT_mount   = BIT( 1),
+   OPT_uts = BIT( 2),
+   OPT_ipc = BIT( 3),
+   OPT_network = BIT( 4),
+   OPT_pid = BIT( 5),
+   OPT_user= BIT( 6),
+   OPT_setuid  = BIT( 7),
+   OPT_setgid  = BIT( 8),
+   OPT_prescred= BIT( 9),
+   OPT_root= BIT(10),
+   OPT_wd  = BIT(11),
+   OPT_nofork  = BIT(12),
+};
+
+enum {
+   NS_USR_POS = 0,
+   NS_IPC_POS,
+   NS_UTS_POS,
+   NS_NET_POS,
+   NS_PID_POS,
+   NS_MNT_POS,

[PATCH v4 2/4] unshare: new applet

2016-03-14 Thread Bartosz Golaszewski
Add a fully featured unshare implementation implementing all arguments
supported in the upstream version.

Signed-off-by: Bartosz Golaszewski 
---
 util-linux/unshare.c | 464 +++
 1 file changed, 464 insertions(+)
 create mode 100644 util-linux/unshare.c

diff --git a/util-linux/unshare.c b/util-linux/unshare.c
new file mode 100644
index 000..d1394a9
--- /dev/null
+++ b/util-linux/unshare.c
@@ -0,0 +1,464 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini unshare implementation for busybox.
+ *
+ * Copyright (C) 2016 by Bartosz Golaszewski 
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
+ */
+
+//config:config UNSHARE
+//config:  bool "unshare"
+//config:  default y
+//config:  select PLATFORM_LINUX
+//config:  help
+//config:Run program with some namespaces unshared from parent.
+//config:
+//config:config FEATURE_UNSHARE_LONG_OPTS
+//config:  bool "enable long options"
+//config:  default y
+//config:  depends on UNSHARE && LONG_OPTS
+//config:  help
+//config:Support long options for the unshare applet. This makes
+//config:the busybox implementation more compatible with upstream.
+
+//applet:IF_UNSHARE(APPLET(unshare, BB_DIR_USR_BIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_UNSHARE) += unshare.o
+
+//usage:#define unshare_trivial_usage
+//usage:   "[options]  [args...]"
+//usage:#if ENABLE_FEATURE_UNSHARE_LONG_OPTS
+//usage:#define unshare_full_usage "\n\n"
+//usage:   "Options:"
+//usage: "\n   -m, --mount[=]unshare mounts 
namespace"
+//usage: "\n   -u, --uts[=]  unshare UTS namespace 
(hostname etc.)"
+//usage: "\n   -i, --ipc[=]  unshare System V IPC 
namespace"
+//usage: "\n   -n, --network[=]  unshare network 
namespace"
+//usage: "\n   -p, --pid[=]  unshare pid namespace"
+//usage: "\n   -U, --user[=] unshare user namespace"
+//usage: "\n   -f, --fork  fork before launching 
"
+//usage: "\n   -M, --mount-proc[=]mount proc filesystem 
first (implies --mount)"
+//usage: "\n   -r, --map-root-user map current user to 
root (implies --user)"
+//usage: "\n   -P, --propagation slave|shared|private|unchanged"
+//usage: "\n   modify mount 
propagation in mount namespace"
+//usage: "\n   -s, --setgroups allow|deny  control the setgroups 
syscall in user namespaces"
+//usage:#else
+//usage:#define unshare_full_usage "\n\n"
+//usage:   "Options:"
+//usage: "\n   -m [] unshare mounts namespace"
+//usage: "\n   -u [] unshare UTS namespace (hostname etc.)"
+//usage: "\n   -i [] unshare System V IPC namespace"
+//usage: "\n   -n [] unshare network namespace"
+//usage: "\n   -p [] unshare pid namespace"
+//usage: "\n   -U [] unshare user namespace"
+//usage: "\n   -f  fork before launching "
+//usage: "\n   -M []  mount proc filesystem first (implies 
-m)"
+//usage: "\n   -r  map current user to root (implies -u)"
+//usage: "\n   -P slave|shared|private|unchanged"
+//usage: "\n   modify mount propagation in mount 
namespace"
+//usage: "\n   -s allow|deny   ontrol the setgroups syscall in user 
namespaces"
+//usage:#endif
+
+#include "libbb.h"
+
+#include 
+#include 
+#include 
+
+/*
+ * Longest possible path to a procfs file used in unshare. Must be able to
+ * contain the '/proc/' string, the '/ns/user' string which is the longest
+ * namespace name and a 32-bit integer representing the process ID.
+ */
+#define PROC_PATH_MAX  (sizeof("/proc//ns/user") + sizeof(pid_t) * 3)
+
+#define PATH_PROC_SETGROUPS"/proc/self/setgroups"
+#define PATH_PROC_UIDMAP   "/proc/self/uid_map"
+#define PATH_PROC_GIDMAP   "/proc/self/gid_map"
+
+enum {
+   OPT_mount   = BIT( 0),
+   OPT_uts = BIT( 1),
+   OPT_ipc = BIT( 2),
+   OPT_network = BIT( 3),
+   OPT_pid = BIT( 4),
+   OPT_user= BIT( 5),
+   OPT_fork= BIT( 6),
+   OPT_mount_proc  = BIT( 7),
+   OPT_map_root= BIT( 8),
+   OPT_propagation = BIT( 9),
+   OPT_setgroups   = BIT(10),
+};
+
+enum {
+   NS_MNT_POS = 0,
+   NS_UTS_POS,
+   NS_IPC_POS,
+   NS_NET_POS,
+   NS_PID_POS,
+   NS_USR_POS,
+   NS_COUNT,
+};
+
+struct namespace_descr {
+   const int opt;
+   const int flag;
+   const char *nsfile;
+};
+
+struct namespace_ctx {
+   char *path;
+};
+
+struct propagation_mode {
+   const char *name;
+   unsigned long flags;
+};
+
+/*
+ * Upstream unshare doesn't support short options for --mount-proc and
+ * --propagation, but let's add them here to let the user use them even with
+ * lon

[PATCH v4 1/4] libbb: add BIT() macro

2016-03-14 Thread Bartosz Golaszewski
This macro - taken from the linux kernel source - improves readability
of single bit definitions.

Signed-off-by: Bartosz Golaszewski 
---
 include/libbb.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/libbb.h b/include/libbb.h
index d05ac29..fcad060 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -292,6 +292,8 @@ struct BUG_off_t_size_is_misdetected {
 #undef SKIP
 #define SKIP   ((int) 2)
 
+#define BIT(nr) (1UL << (nr))
+
 /* Macros for min/max.  */
 #ifndef MIN
 #define MIN(a,b) (((a)<(b))?(a):(b))
-- 
2.1.4

___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: [PATCH v3 3/4] nsenter: new applet

2016-03-14 Thread Mike Frysinger
On 14 Mar 2016 11:07, Bartosz Golaszewski wrote:
> +#ifndef __BB_NAMESPACE_H
> +#define __BB_NAMESPACE_H

use a naming style like other busybox headers

> +/*
> + * Longest possible path to a procfs file used in namespace utils. Must be
> + * able to contain the '/proc/' string, the '/ns/user' string which is the
> + * longest namespace name and a 32-bit integer representing the process ID.
> + */
> +#define NS_PROC_PATH_MAX (sizeof("/proc//ns/user") + sizeof(pid_t) * 3)

using the sizeof pid_t as a proxy for how many chars it'd take to render
a decimal number in ASCII is wonky.  just hardcode it as "10" since that
is the largest unsigned 32bit number ("4294967296").

> + status = setgid(gid);
> + if (status < 0)
> + bb_perror_msg_and_die("setgid failed");

use xsetgid

> + status = setuid(uid);
> + if (status < 0)
> + bb_perror_msg_and_die("setuid failed");

use xsetuid
-mike


signature.asc
Description: Digital signature
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox

Re: [PATCH v2 2/4] unshare: new applet

2016-03-14 Thread Mike Frysinger
On 14 Mar 2016 11:08, Bartosz Gołaszewski wrote:
> 2016-03-11 18:24 GMT+01:00 Mike Frysinger :
> > On 11 Mar 2016 18:10, Bartosz Golaszewski wrote:
> >> +int unshare_main(int argc UNUSED_PARAM, char **argv)
> >> +{
> >> + static struct namespace ns_list[] = {
> >
> > const ?
> >
> 
> Nope, we're using char *path to store the mount points.

that's kind of a big chunk of data to blend read-only & writable
data in.  can't you create a parallel array just for the writable
data and use the indices you have now to index it ?
-mike


signature.asc
Description: Digital signature
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox

Re: [PATCH v2 2/4] unshare: new applet

2016-03-14 Thread Bartosz Gołaszewski
2016-03-11 18:24 GMT+01:00 Mike Frysinger :
> On 11 Mar 2016 18:10, Bartosz Golaszewski wrote:
>> +int unshare_main(int argc UNUSED_PARAM, char **argv)
>> +{
>> + static struct namespace ns_list[] = {
>
> const ?
>

Nope, we're using char *path to store the mount points.

>> + {
>> +#define NS_MNT_POS 0
>
> perhaps an alternate way of handling these indices:
> enum {
> NS_MNT_POS = 0,
> NS_UTS_POS,
> NS_IPC_POS,
> NS_NET_POS,
> ...
> };
> static struct namespace ns_list[] = {
> [NS_MNT_POS] = {
> ...
> -mike

Looks better indeed, fixed in v3.

-- 
Best regards,
Bartosz Golaszewski
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


[PATCH v3 4/4] namespace utils: code shrink

2016-03-14 Thread Bartosz Golaszewski
Both unshare and nsenter use similar code to fork and have the parent
wait for child's completion. Move it to a common library function.

function old new   delta
continue_as_child  - 105+105
unshare_main10661004 -62
nsenter_main 850 753 -97
--
(add/remove: 2/0 grow/shrink: 0/2 up/down: 105/-159)  Total: -54 bytes
   textdata bss dec hex filename
 82955244869120  843158   cdd96 busybox_old
 82949844869120  843104   cdd60 busybox_unstripped

Signed-off-by: Bartosz Golaszewski 
---
 util-linux/namespace.c | 34 ++
 util-linux/namespace.h |  7 +++
 util-linux/nsenter.c   | 20 ++--
 util-linux/unshare.c   | 19 ++-
 4 files changed, 45 insertions(+), 35 deletions(-)
 create mode 100644 util-linux/namespace.c

diff --git a/util-linux/namespace.c b/util-linux/namespace.c
new file mode 100644
index 000..1cfa1ae
--- /dev/null
+++ b/util-linux/namespace.c
@@ -0,0 +1,34 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Common namespace code.
+ *
+ * Copyright (C) 2016 by Bartosz Golaszewski 
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
+ */
+
+//kbuild:lib-$(CONFIG_UNSHARE) += namespace.o
+//kbuild:lib-$(CONFIG_NSENTER) += namespace.o
+
+#include "libbb.h"
+#include "namespace.h"
+
+void continue_as_child(void)
+{
+   int exit_status, rv;
+   pid_t pid;
+
+   pid = xfork();
+   if (pid > 0) {
+   rv = safe_waitpid(pid, &exit_status, WUNTRACED);
+   if (rv < 0)
+   bb_perror_msg_and_die("waitpid");
+
+   if (WIFEXITED(exit_status))
+   exit(WEXITSTATUS(exit_status));
+   else if (WIFSIGNALED(exit_status))
+   kill(getpid(), WTERMSIG(exit_status));
+
+   bb_error_msg_and_die("child exit failed");
+   } /* Child continues. */
+}
diff --git a/util-linux/namespace.h b/util-linux/namespace.h
index da79fd9..42e8361 100644
--- a/util-linux/namespace.h
+++ b/util-linux/namespace.h
@@ -17,4 +17,11 @@
  */
 #define NS_PROC_PATH_MAX (sizeof("/proc//ns/user") + sizeof(pid_t) * 3)
 
+/*
+ * Fork and wait for the child process to finish. Exit with the child process'
+ * exit status or deliver the signal which killed the child to the parent.
+ * Exit if fork() or waitpid() fails.
+ */
+void continue_as_child(void);
+
 #endif /* __BB_NAMESPACE_H */
diff --git a/util-linux/nsenter.c b/util-linux/nsenter.c
index 7beaddb..8e9247a 100644
--- a/util-linux/nsenter.c
+++ b/util-linux/nsenter.c
@@ -318,24 +318,8 @@ int nsenter_main(int argc UNUSED_PARAM, char **argv)
 * Entering the pid namespace implies forking unless it's been
 * explicitly requested by the user not to.
 */
-   if (!(opts & OPT_nofork) && (opts & OPT_pid)) {
-   int exit_status;
-   pid_t pid;
-
-   pid = xfork();
-   if (pid > 0) {
-   status = safe_waitpid(pid, &exit_status, 0);
-   if (status < 0)
-   bb_perror_msg_and_die("waitpid");
-
-   if (WIFEXITED(exit_status))
-   return WEXITSTATUS(exit_status);
-   else if (WIFSIGNALED(exit_status))
-   kill(getpid(), WTERMSIG(exit_status));
-
-   bb_error_msg_and_die("child exit failed");
-   } /* Child continues. */
-   }
+   if (!(opts & OPT_nofork) && (opts & OPT_pid))
+   continue_as_child();
 
if (opts & OPT_setgid) {
status = setgroups(0, NULL);
diff --git a/util-linux/unshare.c b/util-linux/unshare.c
index b6146e3..637ff2a 100644
--- a/util-linux/unshare.c
+++ b/util-linux/unshare.c
@@ -386,23 +386,8 @@ int unshare_main(int argc UNUSED_PARAM, char **argv)
 * child. The user may want to use this option to spawn a new process
 * that'll become PID 1 in this new namespace.
 */
-   if (opts & OPT_fork) {
-   int exit_status;
-
-   pid = xfork();
-   if (pid > 0) {
-   status = safe_waitpid(pid, &exit_status, 0);
-   if (status < 0)
-   bb_perror_msg_and_die("waitpid");
-
-   if (WIFEXITED(exit_status))
-   return WEXITSTATUS(exit_status);
-   else if (WIFSIGNALED(exit_status))
-   kill(getpid(), WTERMSIG(exit_status));
-
-   bb_error_msg_and_die("child exit failed");
-   } /* Child continues. */
-   }
+   if (opts & OPT_fork)

[PATCH v3 0/4] util-linux: namespace utils

2016-03-14 Thread Bartosz Golaszewski
This series adds two namespaces-related applets reimplementing most
arguments supported by their upstream util-linux counterparts.

The fourth patch is an optional code shrink.

v3:
- moved the namespace positions into an enum for better readability

v2:
- v1 was badly rebased and patch 3/4 didn't compile - fixed it
- added some parenthesis for better readability in patch 3/4

v1: http://lists.busybox.net/pipermail/busybox/2016-March/083957.html

Bartosz Golaszewski (4):
  libbb: add BIT() macro
  unshare: new applet
  nsenter: new applet
  namespace utils: code shrink

 include/libbb.h|   2 +
 util-linux/namespace.c |  34 
 util-linux/namespace.h |  27 
 util-linux/nsenter.c   | 346 +++
 util-linux/unshare.c   | 432 +
 5 files changed, 841 insertions(+)
 create mode 100644 util-linux/namespace.c
 create mode 100644 util-linux/namespace.h
 create mode 100644 util-linux/nsenter.c
 create mode 100644 util-linux/unshare.c

-- 
2.1.4

___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


[PATCH v3 2/4] unshare: new applet

2016-03-14 Thread Bartosz Golaszewski
Add a fully featured unshare implementation implementing all arguments
supported in the upstream version.

Signed-off-by: Bartosz Golaszewski 
---
 util-linux/unshare.c | 453 +++
 1 file changed, 453 insertions(+)
 create mode 100644 util-linux/unshare.c

diff --git a/util-linux/unshare.c b/util-linux/unshare.c
new file mode 100644
index 000..ea9ec9c
--- /dev/null
+++ b/util-linux/unshare.c
@@ -0,0 +1,453 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini unshare implementation for busybox.
+ *
+ * Copyright (C) 2016 by Bartosz Golaszewski 
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
+ */
+
+//config:config UNSHARE
+//config:  bool "unshare"
+//config:  default y
+//config:  select PLATFORM_LINUX
+//config:  help
+//config:Run program with some namespaces unshared from parent.
+//config:
+//config:config FEATURE_UNSHARE_LONG_OPTS
+//config:  bool "enable long options"
+//config:  default y
+//config:  depends on UNSHARE && LONG_OPTS
+//config:  help
+//config:Support long options for the unshare applet. This makes
+//config:the busybox implementation more compatible with upstream.
+
+//applet:IF_UNSHARE(APPLET(unshare, BB_DIR_USR_BIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_UNSHARE) += unshare.o
+
+//usage:#define unshare_trivial_usage
+//usage:   "[options]  [args...]"
+//usage:#if ENABLE_FEATURE_UNSHARE_LONG_OPTS
+//usage:#define unshare_full_usage "\n\n"
+//usage:   "Options:"
+//usage: "\n   -m, --mount[=]unshare mounts 
namespace"
+//usage: "\n   -u, --uts[=]  unshare UTS namespace 
(hostname etc.)"
+//usage: "\n   -i, --ipc[=]  unshare System V IPC 
namespace"
+//usage: "\n   -n, --network[=]  unshare network 
namespace"
+//usage: "\n   -p, --pid[=]  unshare pid namespace"
+//usage: "\n   -U, --user[=] unshare user namespace"
+//usage: "\n   -f, --fork  fork before launching 
"
+//usage: "\n   -M, --mount-proc[=]mount proc filesystem 
first (implies --mount)"
+//usage: "\n   -r, --map-root-user map current user to 
root (implies --user)"
+//usage: "\n   -P, --propagation slave|shared|private|unchanged"
+//usage: "\n   modify mount 
propagation in mount namespace"
+//usage: "\n   -s, --setgroups allow|deny  control the setgroups 
syscall in user namespaces"
+//usage:#else
+//usage:#define unshare_full_usage "\n\n"
+//usage:   "Options:"
+//usage: "\n   -m [] unshare mounts namespace"
+//usage: "\n   -u [] unshare UTS namespace (hostname etc.)"
+//usage: "\n   -i [] unshare System V IPC namespace"
+//usage: "\n   -n [] unshare network namespace"
+//usage: "\n   -p [] unshare pid namespace"
+//usage: "\n   -U [] unshare user namespace"
+//usage: "\n   -f  fork before launching "
+//usage: "\n   -M []  mount proc filesystem first (implies 
-m)"
+//usage: "\n   -r  map current user to root (implies -u)"
+//usage: "\n   -P slave|shared|private|unchanged"
+//usage: "\n   modify mount propagation in mount 
namespace"
+//usage: "\n   -s allow|deny   ontrol the setgroups syscall in user 
namespaces"
+//usage:#endif
+
+#include "libbb.h"
+
+#include 
+#include 
+#include 
+
+/*
+ * Longest possible path to a procfs file used in unshare. Must be able to
+ * contain the '/proc/' string, the '/ns/user' string which is the longest
+ * namespace name and a 32-bit integer representing the process ID.
+ */
+#define PROC_PATH_MAX   (sizeof("/proc//ns/user") + sizeof(pid_t) * 3)
+
+#define PATH_PROC_SETGROUPS"/proc/self/setgroups"
+#define PATH_PROC_UIDMAP   "/proc/self/uid_map"
+#define PATH_PROC_GIDMAP   "/proc/self/gid_map"
+
+enum {
+   OPT_mount   = BIT( 0),
+   OPT_uts = BIT( 1),
+   OPT_ipc = BIT( 2),
+   OPT_network = BIT( 3),
+   OPT_pid = BIT( 4),
+   OPT_user= BIT( 5),
+   OPT_fork= BIT( 6),
+   OPT_mount_proc  = BIT( 7),
+   OPT_map_root= BIT( 8),
+   OPT_propagation = BIT( 9),
+   OPT_setgroups   = BIT(10),
+};
+
+enum {
+   NS_MNT_POS = 0,
+   NS_UTS_POS,
+   NS_IPC_POS,
+   NS_NET_POS,
+   NS_PID_POS,
+   NS_USR_POS,
+};
+
+struct namespace {
+   const int opt;
+   const int flag;
+   const char *nsfile;
+   char *path;
+};
+
+struct propagation_mode {
+   const char *name;
+   unsigned long flags;
+};
+
+/*
+ * Upstream unshare doesn't support short options for --mount-proc and
+ * --propagation, but let's add them here to let the user use them even with
+ * long options disabled in busybox config.
+ */
+static co

[PATCH v3 1/4] libbb: add BIT() macro

2016-03-14 Thread Bartosz Golaszewski
This macro - taken from the linux kernel source - improves readability
of single bit definitions.

Signed-off-by: Bartosz Golaszewski 
---
 include/libbb.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/libbb.h b/include/libbb.h
index d05ac29..fcad060 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -292,6 +292,8 @@ struct BUG_off_t_size_is_misdetected {
 #undef SKIP
 #define SKIP   ((int) 2)
 
+#define BIT(nr) (1UL << (nr))
+
 /* Macros for min/max.  */
 #ifndef MIN
 #define MIN(a,b) (((a)<(b))?(a):(b))
-- 
2.1.4

___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


[PATCH v3 3/4] nsenter: new applet

2016-03-14 Thread Bartosz Golaszewski
Implement a fully featured (sans selinux part) nsenter applet.

Signed-off-by: Bartosz Golaszewski 
---
 util-linux/namespace.h |  20 +++
 util-linux/nsenter.c   | 362 +
 util-linux/unshare.c   |  12 +-
 3 files changed, 385 insertions(+), 9 deletions(-)
 create mode 100644 util-linux/namespace.h
 create mode 100644 util-linux/nsenter.c

diff --git a/util-linux/namespace.h b/util-linux/namespace.h
new file mode 100644
index 000..da79fd9
--- /dev/null
+++ b/util-linux/namespace.h
@@ -0,0 +1,20 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Common namespace code.
+ *
+ * Copyright (C) 2016 by Bartosz Golaszewski 
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
+ */
+
+#ifndef __BB_NAMESPACE_H
+#define __BB_NAMESPACE_H
+
+/*
+ * Longest possible path to a procfs file used in namespace utils. Must be
+ * able to contain the '/proc/' string, the '/ns/user' string which is the
+ * longest namespace name and a 32-bit integer representing the process ID.
+ */
+#define NS_PROC_PATH_MAX (sizeof("/proc//ns/user") + sizeof(pid_t) * 3)
+
+#endif /* __BB_NAMESPACE_H */
diff --git a/util-linux/nsenter.c b/util-linux/nsenter.c
new file mode 100644
index 000..7beaddb
--- /dev/null
+++ b/util-linux/nsenter.c
@@ -0,0 +1,362 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Mini nsenter implementation for busybox.
+ *
+ * Copyright (C) 2016 by Bartosz Golaszewski 
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
+ */
+
+//config:config NSENTER
+//config:  bool "nsenter"
+//config:  default y
+//config:  select PLATFORM_LINUX
+//config:  help
+//config:Run program with namespaces of other processes.
+//config:
+//config:config FEATURE_NSENTER_LONG_OPTS
+//config:  bool "enable long options"
+//config:  default y
+//config:  depends on NSENTER && LONG_OPTS
+//config:  help
+//config:Support long options for the nsenter applet. This makes
+//config:the busybox implementation more compatible with upstream.
+
+//applet:IF_NSENTER(APPLET(nsenter, BB_DIR_USR_BIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_NSENTER) += nsenter.o
+
+//usage:#define nsenter_trivial_usage
+//usage:   "[options]  [args...]"
+//usage:#if ENABLE_FEATURE_NSENTER_LONG_OPTS
+//usage:#define nsenter_full_usage "\n\n"
+//usage:   "Options:"
+//usage: "\n   -t, --target   target process to get 
namespaces from"
+//usage: "\n   -m, --mount[=]enter mount namespace"
+//usage: "\n   -u, --uts[=]  enter UTS namespace 
(hostname etc)"
+//usage: "\n   -i, --ipc[=]  enter System V IPC 
namespace"
+//usage: "\n   -n, --net[=]  enter network namespace"
+//usage: "\n   -p, --pid[=]  enter pid namespace"
+//usage: "\n   -U, --user[=] enter user namespace"
+//usage: "\n   -S, --setuid   set uid in entered 
namespace"
+//usage: "\n   -G, --setgid   set gid in entered 
namespace"
+//usage: "\n   -P, --preserve-credentials  do not touch uids or 
gids"
+//usage: "\n   -r, --root[=]  set the root directory"
+//usage: "\n   -w, --wd[=]set the working 
directory"
+//usage: "\n   -F, --no-fork   do not fork before 
exec'ing "
+//usage:#else
+//usage:#define nsenter_full_usage "\n\n"
+//usage:   "Options:"
+//usage: "\n   -t target process to get namespaces from"
+//usage: "\n   -m [] enter mount namespace"
+//usage: "\n   -u [] enter UTS namespace (hostname etc)"
+//usage: "\n   -i [] enter System V IPC namespace"
+//usage: "\n   -n [] enter network namespace"
+//usage: "\n   -p [] enter pid namespace"
+//usage: "\n   -U [] enter user namespace"
+//usage: "\n   -S set uid in entered namespace"
+//usage: "\n   -G set gid in entered namespace"
+//usage: "\n   -P  do not touch uids or gids"
+//usage: "\n   -r []  set the root directory"
+//usage: "\n   -w []  set the working directory"
+//usage: "\n   -F  do not fork before exec'ing "
+//usage:#endif
+
+#include "libbb.h"
+#include "namespace.h"
+
+#include 
+
+enum {
+   OPT_target  = BIT( 0),
+   OPT_mount   = BIT( 1),
+   OPT_uts = BIT( 2),
+   OPT_ipc = BIT( 3),
+   OPT_network = BIT( 4),
+   OPT_pid = BIT( 5),
+   OPT_user= BIT( 6),
+   OPT_setuid  = BIT( 7),
+   OPT_setgid  = BIT( 8),
+   OPT_prescred= BIT( 9),
+   OPT_root= BIT(10),
+   OPT_wd  = BIT(11),
+   OPT_nofork  = BIT(12),
+};
+
+enum {
+   NS_USR_POS = 0,
+   NS_IPC_POS,
+   NS_UTS_POS,
+   NS_NET_POS,
+   NS_PID_POS,
+   NS_MNT_POS,