bug-tar
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Bug-tar] [PATCH] add a numeric offset option for uid and gid manipulati


From: Glauber Costa
Subject: [Bug-tar] [PATCH] add a numeric offset option for uid and gid manipulations
Date: Tue, 12 Mar 2013 13:03:00 +0400

As context, Linux 3.8 now supports user namespaces, which means
we can have unprivileged users running as root in the system, with
capabilities valid only in the namespace they operate on. This works
by establishing a 1:1 mapping between a namespace user and a host user,
where (for instance) uid 0 maps to 10000, 1 to 10001, and so on.

With that, it is extremely useful when unpacking tar archives, to be
able to add that offset to the end result. Specifying a user won't help,
since the tar archive can have many, and keeping permissions will
require a post processing step where all ownership is adjusted.

    * src/common.h: global variables for gid and uid offset.
    * src/extract.c (set_stat): adjust stat information.
    * src/tar.c: new option processing.
    * src/list.c (uid_from_header, gid_from_header): use numeric offset
    * doc/tar.texi: Update.
---
 doc/tar.texi  | 11 +++++++++++
 src/common.h  |  5 +++++
 src/extract.c |  2 +-
 src/list.c    |  4 ++--
 src/tar.c     | 44 ++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 63 insertions(+), 3 deletions(-)

diff --git a/doc/tar.texi b/doc/tar.texi
index 480fe89..ae5f1b0 100644
--- a/doc/tar.texi
+++ b/doc/tar.texi
@@ -3028,6 +3028,17 @@ This option will notify @command{tar} that it should use 
numeric user
 and group IDs when creating a @command{tar} file, rather than names.
 @xref{Attributes}.
 
address@hidden
address@hidden address@hidden:gid_offset}
+
+This option will notify @command{tar} that it should add a fixed offset
+to user and group IDs when extracting a @command{tar} file. It implies
+that all user and group IDs are numeric. It takes as a parameter in the
+form @var{uid_offset:gid_offset} denoting the desiring offsets.
+
+This option is useful for example when unpacking files intended to be
+used within a Linux namespace.
+
 @item -o
 The function of this option depends on the action @command{tar} is
 performing.  When extracting files, @option{-o} is a synonym for
diff --git a/src/common.h b/src/common.h
index 4f7c19f..4def7d0 100644
--- a/src/common.h
+++ b/src/common.h
@@ -236,6 +236,11 @@ GLOBAL int recursion_option;
 
 GLOBAL bool numeric_owner_option;
 
+GLOBAL int numeric_owner_uid_offset;
+GLOBAL int numeric_owner_gid_offset;
+
+#define HAS_OWNER_OFFSET (numeric_owner_uid_offset || numeric_owner_gid_offset)
+
 GLOBAL bool one_file_system_option;
 
 /* Specified value to be put into tar file in place of stat () results, or
diff --git a/src/extract.c b/src/extract.c
index 327b67f..4de6797 100644
--- a/src/extract.c
+++ b/src/extract.c
@@ -360,7 +360,7 @@ set_stat (char const *file_name,
        utime_error (file_name);
     }
 
-  if (0 < same_owner_option && ! interdir)
+  if ((0 < same_owner_option && ! interdir) || HAS_OWNER_OFFSET)
     {
       /* Some systems allow non-root users to give files away.  Once this
         done, it is not possible anymore to change file permissions.
diff --git a/src/list.c b/src/list.c
index 858aa73..5b8eb72 100644
--- a/src/list.c
+++ b/src/list.c
@@ -915,7 +915,7 @@ gid_from_header (const char *p, size_t s)
 {
   return from_header (p, s, "gid_t",
                      TYPE_MINIMUM (gid_t), TYPE_MAXIMUM (gid_t),
-                     false, false);
+                     false, false) + numeric_owner_gid_offset;
 }
 
 static major_t
@@ -981,7 +981,7 @@ uid_from_header (const char *p, size_t s)
 {
   return from_header (p, s, "uid_t",
                      TYPE_MINIMUM (uid_t), TYPE_MAXIMUM (uid_t),
-                     false, false);
+                     false, false) + numeric_owner_uid_offset;
 }
 
 uintmax_t
diff --git a/src/tar.c b/src/tar.c
index c29b4fa..cede1ad 100644
--- a/src/tar.c
+++ b/src/tar.c
@@ -315,6 +315,7 @@ enum
   NO_XATTR_OPTION,
   NULL_OPTION,
   NUMERIC_OWNER_OPTION,
+  NUMERIC_OWNER_OFFSET_OPTION,
   OCCURRENCE_OPTION,
   OLD_ARCHIVE_OPTION,
   ONE_FILE_SYSTEM_OPTION,
@@ -525,6 +526,8 @@ static struct argp_option options[] = {
    N_("extract files as yourself (default for ordinary users)"), GRID+1 },
   {"numeric-owner", NUMERIC_OWNER_OPTION, 0, 0,
    N_("always use numbers for user/group names"), GRID+1 },
+  {"owner-offset", NUMERIC_OWNER_OFFSET_OPTION, N_("UID_OFFSET:GID_OFFSET"), 0,
+   N_("add numeric offset for file owner"), GRID+1 },
   {"preserve-permissions", 'p', 0, 0,
    N_("extract information about file permissions (default for superuser)"),
    GRID+1 },
@@ -2000,6 +2003,43 @@ parse_opt (int key, char *arg, struct argp_state *state)
       numeric_owner_option = true;
       break;
 
+    case NUMERIC_OWNER_OFFSET_OPTION:
+      {
+        char const *num = NULL;
+       char *colon = strchr (arg, ':');
+
+        if (colon)
+          {
+            *colon = '\0';
+            num = colon + 1;
+          }
+
+        if (colon != arg)
+          {
+           uintmax_t uid;
+
+           if (! (xstrtoumax (arg, 0, 10, &uid, "") == LONGINT_OK
+               && uid == (size_t) uid))
+              {
+               USAGE_ERROR ((0, 0, "%s",
+                       _("--owner-offset requires a numeric offset 
argument")));
+              }
+            numeric_owner_uid_offset = uid;
+         }
+
+        if (num)
+          {
+           uintmax_t gid;
+
+            if (! (xstrtoumax (num, 0, 10, &gid, "") == LONGINT_OK
+              && gid == (size_t) gid))
+              USAGE_ERROR ((0, 0, "%s",
+                       _("--owner-offset received an invalid gid")));
+            numeric_owner_gid_offset = gid;
+          }
+
+        break;
+      }
     case OCCURRENCE_OPTION:
       if (!arg)
        occurrence_option = 1;
@@ -2738,6 +2778,10 @@ main (int argc, char **argv)
   filename_terminator = '\n';
   set_quoting_style (0, DEFAULT_QUOTING_STYLE);
 
+  /* in case not set */
+  numeric_owner_uid_offset = 0;
+  numeric_owner_gid_offset = 0;
+
   /* Make sure we have first three descriptors available */
   stdopen ();
 
-- 
1.8.1.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]