Whamcloud - gitweb
LU-9430 utils: fix logic errors and putchar in sk_name2hmac()
[fs/lustre-release.git] / lustre / utils / gss / lgss_keyring.c
index 929a49f..bf936de 100644 (file)
  *
  * You should have received a copy of the GNU General Public License
  * version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
+ * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * GPL HEADER END
  */
@@ -40,6 +36,9 @@
  * Author: Eric Mei <ericm@clusterfs.com>
  */
 
+#include <sched.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -99,21 +98,22 @@ struct lgss_init_res {
 };
 
 struct keyring_upcall_param {
-       uint32_t        kup_ver;
-       uint32_t        kup_secid;
-       uint32_t        kup_uid;
-       uint32_t        kup_fsuid;
-       uint32_t        kup_gid;
-       uint32_t        kup_fsgid;
-       uint32_t        kup_svc;
-       uint64_t        kup_nid;
-       uint64_t        kup_selfnid;
+       uint32_t        kup_ver;
+       uint32_t        kup_secid;
+       uint32_t        kup_uid;
+       uint32_t        kup_fsuid;
+       uint32_t        kup_gid;
+       uint32_t        kup_fsgid;
+       uint32_t        kup_svc;
+       uint64_t        kup_nid;
+       uint64_t        kup_selfnid;
        char            kup_svc_type;
-       char            kup_tgt[64];
-       char            kup_mech[16];
-       unsigned int    kup_is_root:1,
+       char            kup_tgt[64];
+       char            kup_mech[16];
+       unsigned int    kup_is_root:1,
                        kup_is_mdt:1,
                        kup_is_ost:1;
+       uint32_t        kup_pid;
 };
 
 /****************************************
@@ -723,11 +723,12 @@ static int lgssc_kr_negotiate(key_serial_t keyid, struct lgss_cred *cred,
  *  [7]: target_nid     (uint64)
  *  [8]: target_uuid    (string)
  *  [9]: self_nid        (uint64)
+ *  [10]: pid            (uint)
  */
 static int parse_callout_info(const char *coinfo,
                               struct keyring_upcall_param *uparam)
 {
-       const int       nargs = 10;
+       const int       nargs = 11;
        char            buf[1024];
        char           *string = buf;
        int             length, i;
@@ -754,9 +755,9 @@ static int parse_callout_info(const char *coinfo,
         }
         data[i] = string;
 
-       logmsg(LL_TRACE, "components: %s,%s,%s,%s,%s,%c,%s,%s,%s,%s\n",
+       logmsg(LL_TRACE, "components: %s,%s,%s,%s,%s,%c,%s,%s,%s,%s,%s\n",
               data[0], data[1], data[2], data[3], data[4], data[5][0],
-              data[6], data[7], data[8], data[9]);
+              data[6], data[7], data[8], data[9], data[10]);
 
        uparam->kup_secid = strtol(data[0], NULL, 0);
        strlcpy(uparam->kup_mech, data[1], sizeof(uparam->kup_mech));
@@ -773,15 +774,16 @@ static int parse_callout_info(const char *coinfo,
        uparam->kup_nid = strtoll(data[7], NULL, 0);
        strlcpy(uparam->kup_tgt, data[8], sizeof(uparam->kup_tgt));
        uparam->kup_selfnid = strtoll(data[9], NULL, 0);
+       uparam->kup_pid = strtol(data[10], NULL, 0);
 
        logmsg(LL_DEBUG, "parse call out info: secid %d, mech %s, ugid %u:%u, "
               "is_root %d, is_mdt %d, is_ost %d, svc type %c, svc %d, "
-              "nid 0x%"PRIx64", tgt %s, self nid 0x%"PRIx64"\n",
+              "nid 0x%"PRIx64", tgt %s, self nid 0x%"PRIx64", pid %d\n",
               uparam->kup_secid, uparam->kup_mech,
               uparam->kup_uid, uparam->kup_gid,
               uparam->kup_is_root, uparam->kup_is_mdt, uparam->kup_is_ost,
               uparam->kup_svc_type, uparam->kup_svc, uparam->kup_nid,
-              uparam->kup_tgt, uparam->kup_selfnid);
+              uparam->kup_tgt, uparam->kup_selfnid, uparam->kup_pid);
        return 0;
 }
 
@@ -812,6 +814,21 @@ out:
        fclose(file);
 }
 
+#ifdef HAVE_SETNS
+static int associate_with_ns(char *path)
+{
+       int fd, rc = -1;
+
+       fd = open(path, O_RDONLY);
+       if (fd != -1) {
+               rc = setns(fd, 0);
+               close(fd);
+       }
+
+       return rc;
+}
+#endif
+
 /****************************************
  * main process                         *
  ****************************************/
@@ -825,6 +842,10 @@ int main(int argc, char *argv[])
         pid_t                           child;
         struct lgss_mech_type          *mech;
         struct lgss_cred               *cred;
+#ifdef HAVE_SETNS
+       char                            path[PATH_MAX];
+       struct stat parent_ns = { .st_ino = 0 }, caller_ns = { .st_ino = 0 };
+#endif
 
         set_log_level();
 
@@ -918,11 +939,35 @@ int main(int argc, char *argv[])
        cred->lc_svc_type = uparam.kup_svc_type;
        cred->lc_self_nid = uparam.kup_selfnid;
 
-        if (lgss_prepare_cred(cred)) {
-                logmsg(LL_ERR, "key %08x: failed to prepare credentials "
-                       "for user %d\n", keyid, uparam.kup_uid);
-                return 1;
-        }
+#ifdef HAVE_SETNS
+       /* Is caller in different namespace? */
+       snprintf(path, sizeof(path), "/proc/%d/ns/mnt", getpid());
+       if (stat(path, &parent_ns))
+               logmsg(LL_ERR, "cannot stat %s: %s\n", path, strerror(errno));
+       snprintf(path, sizeof(path), "/proc/%d/ns/mnt", uparam.kup_pid);
+       if (stat(path, &caller_ns))
+               logmsg(LL_ERR, "cannot stat %s: %s\n", path, strerror(errno));
+       if (caller_ns.st_ino != parent_ns.st_ino) {
+               /*
+                * do credentials preparation in caller's namespace
+                */
+               if (associate_with_ns(path) != 0) {
+                       logmsg(LL_ERR, "failed to attach to pid %d namespace: "
+                              "%s\n", uparam.kup_pid, strerror(errno));
+                       return 1;
+               }
+               logmsg(LL_TRACE, "working in namespace of pid %d\n",
+                      uparam.kup_pid);
+       } else {
+               logmsg(LL_TRACE, "caller's namespace is the same\n");
+       }
+#endif /* HAVE_SETNS */
+
+       if (lgss_prepare_cred(cred)) {
+               logmsg(LL_ERR, "key %08x: failed to prepare credentials "
+                      "for user %d\n", keyid, uparam.kup_uid);
+               return 1;
+       }
 
         /* pre initialize the key. note the keyring linked to is actually of the
          * original requesting process, not _this_ upcall process. if it's for