Quantcast

[cifs-utils PATCH v3 0/4] cifs.upcall: allow cifs.upcall to scrape cache location initiating task's environment

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[cifs-utils PATCH v3 0/4] cifs.upcall: allow cifs.upcall to scrape cache location initiating task's environment

Jeff Layton-4
Apologies for v3 series, I had some extra patches in there. This is
the one that should have been sent. Relabeled as v4 for clarity.

Third respin of this series. Reordered for better safety for bisecting.
The environment scraping is now on by default, but can be disabled with
"-E" in environments where it's not needed.

Also, I've added a patch to make cifs.upcall drop capabilities before
doing most of its work. This may help reduce the attack surface of the
program.

Jeff Layton (4):
  cifs.upcall: convert two flags from int to bool
  cifs.upcall: switch group IDs when handling an upcall
  cifs.upcall: drop capabilities early in program
  cifs.upcall: allow scraping of KRB5CCNAME out of initiating task's
    /proc/<pid>/environ file

 Makefile.am      |   2 +-
 cifs.upcall.8.in |   9 ++
 cifs.upcall.c    | 255 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 256 insertions(+), 10 deletions(-)

--
2.9.3


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[cifs-utils PATCH v4 1/4] cifs.upcall: convert two flags from int to bool

Jeff Layton-4
Signed-off-by: Jeff Layton <[hidden email]>
---
 cifs.upcall.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/cifs.upcall.c b/cifs.upcall.c
index 8f146c92b4a5..418b179d7f29 100644
--- a/cifs.upcall.c
+++ b/cifs.upcall.c
@@ -685,7 +685,8 @@ int main(const int argc, char *const argv[])
  size_t datalen;
  unsigned int have;
  long rc = 1;
- int c, try_dns = 0, legacy_uid = 0;
+ int c;
+ bool try_dns = false, legacy_uid = false;
  char *buf;
  char hostbuf[NI_MAXHOST], *host;
  struct decoded_args arg;
@@ -705,7 +706,7 @@ int main(const int argc, char *const argv[])
  /* legacy option -- skip it */
  break;
  case 't':
- try_dns++;
+ try_dns = true;
  break;
  case 'k':
  if (setenv("KRB5_CONFIG", optarg, 1) != 0) {
@@ -717,7 +718,7 @@ int main(const int argc, char *const argv[])
  keytab_name = optarg;
  break;
  case 'l':
- legacy_uid++;
+ legacy_uid = true;
  break;
  case 'v':
  rc = 0;
@@ -899,7 +900,7 @@ retry_new_hostname:
  if (rc)
  break;
 
- try_dns = 0;
+ try_dns = false;
  host = hostbuf;
  goto retry_new_hostname;
  default:
--
2.9.3


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[cifs-utils PATCH v4 2/4] cifs.upcall: switch group IDs when handling an upcall

Jeff Layton-4
In reply to this post by Jeff Layton-4
Currently, we leave the group ID alone, but in a later patch we'll be
changing cifs.upcall to scrape $KRB5CCNAME out of the originating
process. At that point, we want to be a little more careful with the
process credentials we'll be using.

After we get the uid, do a getpwuid and grab the default gid for the
user. Then use setgid to set it before calling setuid.

Signed-off-by: Jeff Layton <[hidden email]>
---
 cifs.upcall.c | 37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/cifs.upcall.c b/cifs.upcall.c
index 418b179d7f29..2b535a133a30 100644
--- a/cifs.upcall.c
+++ b/cifs.upcall.c
@@ -46,6 +46,8 @@
 #include <netdb.h>
 #include <arpa/inet.h>
 #include <ctype.h>
+#include <pwd.h>
+#include <grp.h>
 
 #include "replace.h"
 #include "data_blob.h"
@@ -694,6 +696,7 @@ int main(const int argc, char *const argv[])
  uid_t uid;
  char *keytab_name = NULL;
  krb5_ccache ccache = NULL;
+ struct passwd *pw;
 
  hostbuf[0] = '\0';
  memset(&arg, 0, sizeof(arg));
@@ -795,15 +798,49 @@ int main(const int argc, char *const argv[])
  goto out;
  }
 
+ /*
+ * The kernel doesn't pass down the gid, so we resort here to scraping
+ * one out of the passwd nss db. Note that this might not reflect the
+ * actual gid of the process that initiated the upcall. While we could
+ * scrape that out of /proc, relying on that is a bit more risky.
+ */
+ pw = getpwuid(uid);
+ if (!pw) {
+ syslog(LOG_ERR, "Unable to find pw entry for uid %d: %s\n",
+ uid, strerror(errno));
+ rc = 1;
+ goto out;
+ }
+
+ /*
+ * The kernel should send down a zero-length grouplist already, but
+ * just to be on the safe side...
+ */
+ rc = setgroups(0, NULL);
+ if (rc == -1) {
+ syslog(LOG_ERR, "setgroups: %s", strerror(errno));
+ rc = 1;
+ goto out;
+ }
+
+ rc = setgid(pw->pw_gid);
+ if (rc == -1) {
+ syslog(LOG_ERR, "setgid: %s", strerror(errno));
+ rc = 1;
+ goto out;
+ }
+
  rc = setuid(uid);
  if (rc == -1) {
  syslog(LOG_ERR, "setuid: %s", strerror(errno));
+ rc = 1;
  goto out;
  }
 
  rc = krb5_init_context(&context);
  if (rc) {
  syslog(LOG_ERR, "unable to init krb5 context: %ld", rc);
+ rc = 1;
  goto out;
  }
 
--
2.9.3


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[cifs-utils PATCH v4 3/4] cifs.upcall: drop capabilities early in program

Jeff Layton-4
In reply to this post by Jeff Layton-4
Much of cifs.upcall can and should be run without elevated privileges.
On entry into the program, drop as many capabilities as we can get away
with, and then always drop any remaining caps after calling setuid().

Signed-off-by: Jeff Layton <[hidden email]>
---
 Makefile.am   |  2 +-
 cifs.upcall.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 64 insertions(+), 1 deletion(-)

diff --git a/Makefile.am b/Makefile.am
index 2e99e601049a..4823b6381082 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -16,7 +16,7 @@ clean-local: clean-local-upcall clean-local-idmap clean-local-cifsacl
 if CONFIG_CIFSUPCALL
 sbin_PROGRAMS += cifs.upcall
 cifs_upcall_SOURCES = cifs.upcall.c data_blob.c asn1.c spnego.c
-cifs_upcall_LDADD = -ltalloc -lkeyutils $(KRB5_LDADD)
+cifs_upcall_LDADD = -ltalloc -lkeyutils $(KRB5_LDADD) $(CAPNG_LDADD)
 man_MANS += cifs.upcall.8
 
 #
diff --git a/cifs.upcall.c b/cifs.upcall.c
index 2b535a133a30..25af0fb6957b 100644
--- a/cifs.upcall.c
+++ b/cifs.upcall.c
@@ -54,6 +54,10 @@
 #include "spnego.h"
 #include "cifs_spnego.h"
 
+#ifdef HAVE_LIBCAP_NG
+#include <cap-ng.h>
+#endif
+
 static krb5_context context;
 static const char *prog = "cifs.upcall";
 
@@ -63,6 +67,58 @@ typedef enum _sectype {
  MS_KRB5
 } sectype_t;
 
+#ifdef HAVE_LIBCAP_NG
+static int
+trim_capabilities(bool need_ptrace)
+{
+ capng_clear(CAPNG_SELECT_BOTH);
+
+ /*
+ * Need ptrace for environment scraping, and setuid to change uid
+ */
+ if (capng_updatev(CAPNG_ADD, CAPNG_PERMITTED|CAPNG_EFFECTIVE,
+ CAP_SETUID, CAP_SETGID, CAP_DAC_OVERRIDE, -1)) {
+ syslog(LOG_ERR, "%s: Unable to update capability set: %m\n", __func__);
+ return 1;
+ }
+
+ if (need_ptrace &&
+    capng_update(CAPNG_ADD, CAPNG_PERMITTED|CAPNG_EFFECTIVE, CAP_SYS_PTRACE)) {
+ syslog(LOG_ERR, "%s: Unable to update capability set: %m\n", __func__);
+ return 1;
+ }
+
+ if (capng_apply(CAPNG_SELECT_BOTH)) {
+ syslog(LOG_ERR, "%s: Unable to apply capability set: %m\n", __func__);
+ return 1;
+ }
+ return 0;
+}
+
+static int
+drop_all_capabilities(void)
+{
+ capng_clear(CAPNG_SELECT_BOTH);
+ if (capng_apply(CAPNG_SELECT_BOTH)) {
+ syslog(LOG_ERR, "%s: Unable to apply capability set: %m\n", __func__);
+ return 1;
+ }
+ return 0;
+}
+#else /* HAVE_LIBCAP_NG */
+static int
+trim_capabilities(void)
+{
+ return 0;
+}
+
+static int
+drop_all_capabilities(void)
+{
+ return 0;
+}
+#endif /* HAVE_LIBCAP_NG */
+
 /*
  * smb_krb5_principal_get_realm
  *
@@ -733,6 +789,9 @@ int main(const int argc, char *const argv[])
  }
  }
 
+ if (trim_capabilities(false))
+ goto out;
+
  /* is there a key? */
  if (argc <= optind) {
  usage();
@@ -837,6 +896,10 @@ int main(const int argc, char *const argv[])
  goto out;
  }
 
+ rc = drop_all_capabilities();
+ if (rc)
+ goto out;
+
  rc = krb5_init_context(&context);
  if (rc) {
  syslog(LOG_ERR, "unable to init krb5 context: %ld", rc);
--
2.9.3


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[cifs-utils PATCH v4 4/4] cifs.upcall: allow scraping of KRB5CCNAME out of initiating task's /proc/<pid>/environ file

Jeff Layton-4
In reply to this post by Jeff Layton-4
Chad reported that he was seeing a regression in cifs-utils-6.6. Prior
to that, cifs.upcall was able to find credcaches in non-default FILE:
locations, but with the rework of that code, that ability was lost.

Unfortunately, the krb5 library design doesn't really take into account
the fact that we might need to find a credcache in a process that isn't
descended from the session.

When the kernel does an upcall, it passes several bits of info about the
task that initiated the upcall. One of those things is the PID (the
tgid, in particular). We can use that info to reach into the
/proc/<pid>/environ file for the process, and grab whatever value of
$KRB5CCNAME is there.

Then, after switching credentials, set $KRB5CCNAME in the environment
to the same value before opening the credcache, to hint to the krb5
libs where they ought to look.

This new behavior is on by default, but can be disabled by having
request-key pass a '-E' flag to cifs.upcall.

Reported-by: Chad William Seys <[hidden email]>
Signed-off-by: Jeff Layton <[hidden email]>
---
 cifs.upcall.8.in |   9 ++++
 cifs.upcall.c    | 150 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 152 insertions(+), 7 deletions(-)

diff --git a/cifs.upcall.8.in b/cifs.upcall.8.in
index 50f79d18331d..e1f3956e176a 100644
--- a/cifs.upcall.8.in
+++ b/cifs.upcall.8.in
@@ -38,6 +38,15 @@ for a particular key type\&. While it can be run directly from the command\-line
 This option is deprecated and is currently ignored\&.
 .RE
 .PP
+\-\-no-env-probe|\-E
+.RS 4
+Normally, cifs.upcall will probe the environment variable space of the process
+that initiated the upcall in order to fetch the value of $KRB5CCNAME. This can
+assist the program with finding credential caches in non-default locations. If
+this option is set, then the program won't do this and will rely on finding
+credcaches in the default locations specified in krb5.conf.
+.RE
+.PP
 \--krb5conf=/path/to/krb5.conf|-k /path/to/krb5.conf
 .RS 4
 This option allows administrators to set an alternate location for the
diff --git a/cifs.upcall.c b/cifs.upcall.c
index 25af0fb6957b..c9ddd35856a9 100644
--- a/cifs.upcall.c
+++ b/cifs.upcall.c
@@ -40,6 +40,7 @@
 #include <dirent.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <fcntl.h>
 #include <unistd.h>
 #include <keyutils.h>
 #include <time.h>
@@ -212,11 +213,125 @@ err_cache:
  return credtime;
 }
 
+#define ENV_PATH_FMT "/proc/%d/environ"
+#define ENV_PATH_MAXLEN (6 + 10 + 8 + 1)
+
+#define ENV_NAME "KRB5CCNAME"
+#define ENV_PREFIX "KRB5CCNAME="
+#define ENV_PREFIX_LEN 11
+
+#define ENV_BUF_START (4096)
+#define ENV_BUF_MAX (131072)
+
+/**
+ * get_cachename_from_process_env - scrape value of $KRB5CCNAME out of the
+ *    initiating process' environment.
+ * @pid: initiating pid value from the upcall string
+ *
+ * Open the /proc/<pid>/environ file for the given pid, and scrape it for
+ * KRB5CCNAME entries.
+ *
+ * We start with a page-size buffer, and then progressively double it until
+ * we can slurp in the whole thing.
+ *
+ * Note that this is not entirely reliable. If the process is sitting in a
+ * container or something, then this is almost certainly not going to point
+ * where you expect.
+ *
+ * Probably it just won't work, but could a user use this to trick cifs.upcall
+ * into reading a file outside the container, by setting KRB5CCNAME in a
+ * crafty way?
+ */
+static char *
+get_cachename_from_process_env(pid_t pid)
+{
+ int fd, ret;
+ ssize_t buflen;
+ ssize_t bufsize = ENV_BUF_START;
+ char pathname[ENV_PATH_MAXLEN];
+ char *cachename = NULL;
+ char *buf = NULL, *pos;
+
+ if (!pid) {
+ syslog(LOG_DEBUG, "%s: pid == 0\n", __func__);
+ return NULL;
+ }
+
+ pathname[ENV_PATH_MAXLEN - 1] = '\0';
+ ret = snprintf(pathname, ENV_PATH_MAXLEN, ENV_PATH_FMT, pid);
+ if (ret >= ENV_PATH_MAXLEN) {
+ syslog(LOG_DEBUG, "%s: unterminated path!\n", __func__);
+ return NULL;
+ }
+
+ syslog(LOG_DEBUG, "%s: pathname=%s\n", __func__, pathname);
+ fd = open(pathname, O_RDONLY);
+ if (fd < 0) {
+ syslog(LOG_DEBUG, "%s: open failed: %d\n", __func__, errno);
+ return NULL;
+ }
+retry:
+ if (bufsize > ENV_BUF_MAX) {
+ syslog(LOG_DEBUG, "%s: buffer too big: %zd\n",
+ __func__, bufsize);
+ goto out_close;
+ }
+
+ buf = malloc(bufsize);
+ if (!buf) {
+ syslog(LOG_DEBUG, "%s: malloc failure\n", __func__);
+ goto out_close;
+ }
+
+ buflen = read(fd, buf, bufsize);
+ if (buflen < 0) {
+ syslog(LOG_DEBUG, "%s: read failed: %d\n", __func__, errno);
+ goto out_close;
+ }
+
+ if (buflen >= bufsize) {
+ /* We read to the end of the buffer. Double and try again */
+ syslog(LOG_DEBUG, "%s: read to end of buffer (%zu bytes)\n",
+ __func__, bufsize);
+ free(buf);
+ bufsize *= 2;
+ if (lseek(fd, 0, SEEK_SET) < 0)
+ goto out_close;
+ goto retry;
+ }
+
+ pos = buf;
+ while (buflen > 0) {
+ size_t len = strnlen(pos, buflen);
+
+ if (len > ENV_PREFIX_LEN &&
+    !memcmp(pos, ENV_PREFIX, ENV_PREFIX_LEN)) {
+ cachename = strndup(pos + ENV_PREFIX_LEN,
+ len - ENV_PREFIX_LEN);
+ syslog(LOG_DEBUG, "%s: cachename = %s\n",
+ __func__, cachename);
+ break;
+ }
+ buflen -= (len + 1);
+ pos += (len + 1);
+ }
+out_close:
+ free(buf);
+ close(fd);
+ return cachename;
+}
+
 static krb5_ccache
-get_default_cc(void)
+get_existing_cc(const char *env_cachename)
 {
  krb5_error_code ret;
  krb5_ccache cc;
+ char *cachename;
+
+ if (env_cachename) {
+ if (setenv(ENV_NAME, env_cachename, 1))
+ syslog(LOG_DEBUG, "%s: failed to setenv %d\n", __func__, errno);
+ }
 
  ret = krb5_cc_default(context, &cc);
  if (ret) {
@@ -224,6 +339,14 @@ get_default_cc(void)
  return NULL;
  }
 
+ ret = krb5_cc_get_full_name(context, cc, &cachename);
+ if (ret) {
+ syslog(LOG_DEBUG, "%s: krb5_cc_get_full_name failed: %d\n", __func__, ret);
+ } else {
+ syslog(LOG_DEBUG, "%s: default ccache is %s\n", __func__, cachename);
+ krb5_free_string(context, cachename);
+ }
+
  if (!get_tgt_time(cc)) {
  krb5_cc_close(context, cc);
  cc = NULL;
@@ -231,7 +354,6 @@ get_default_cc(void)
  return cc;
 }
 
-
 static krb5_ccache
 init_cc_from_keytab(const char *keytab_name, const char *user)
 {
@@ -722,10 +844,11 @@ lowercase_string(char *c)
 
 static void usage(void)
 {
- fprintf(stderr, "Usage: %s [ -K /path/to/keytab] [-k /path/to/krb5.conf] [-t] [-v] [-l] key_serial\n", prog);
+ fprintf(stderr, "Usage: %s [ -K /path/to/keytab] [-k /path/to/krb5.conf] [-E] [-t] [-v] [-l] key_serial\n", prog);
 }
 
 static const struct option long_options[] = {
+ {"no-env-probe", 0, NULL, 'E'},
  {"krb5conf", 1, NULL, 'k'},
  {"legacy-uid", 0, NULL, 'l'},
  {"trust-dns", 0, NULL, 't'},
@@ -744,13 +867,14 @@ int main(const int argc, char *const argv[])
  unsigned int have;
  long rc = 1;
  int c;
- bool try_dns = false, legacy_uid = false;
+ bool try_dns = false, legacy_uid = false , env_probe = true;
  char *buf;
  char hostbuf[NI_MAXHOST], *host;
  struct decoded_args arg;
  const char *oid;
  uid_t uid;
  char *keytab_name = NULL;
+ char *env_cachename = NULL;
  krb5_ccache ccache = NULL;
  struct passwd *pw;
 
@@ -759,11 +883,15 @@ int main(const int argc, char *const argv[])
 
  openlog(prog, 0, LOG_DAEMON);
 
- while ((c = getopt_long(argc, argv, "ck:K:ltv", long_options, NULL)) != -1) {
+ while ((c = getopt_long(argc, argv, "cEk:K:ltv", long_options, NULL)) != -1) {
  switch (c) {
  case 'c':
  /* legacy option -- skip it */
  break;
+ case 'E':
+ /* skip probing initiating process env */
+ env_probe = false;
+ break;
  case 't':
  try_dns = true;
  break;
@@ -789,7 +917,7 @@ int main(const int argc, char *const argv[])
  }
  }
 
- if (trim_capabilities(false))
+ if (trim_capabilities(env_probe))
  goto out;
 
  /* is there a key? */
@@ -889,6 +1017,13 @@ int main(const int argc, char *const argv[])
  goto out;
  }
 
+ /*
+ * Must do this before setuid, as we need elevated capabilities to
+ * look at the environ file.
+ */
+ env_cachename =
+ get_cachename_from_process_env(env_probe ?  arg.pid : 0);
+
  rc = setuid(uid);
  if (rc == -1) {
  syslog(LOG_ERR, "setuid: %s", strerror(errno));
@@ -907,7 +1042,7 @@ int main(const int argc, char *const argv[])
  goto out;
  }
 
- ccache = get_default_cc();
+ ccache = get_existing_cc(env_cachename);
  /* Couldn't find credcache? Try to use keytab */
  if (ccache == NULL && arg.username != NULL)
  ccache = init_cc_from_keytab(keytab_name, arg.username);
@@ -1060,6 +1195,7 @@ out:
  SAFE_FREE(arg.ip);
  SAFE_FREE(arg.username);
  SAFE_FREE(keydata);
+ SAFE_FREE(env_cachename);
  syslog(LOG_DEBUG, "Exit status %ld", rc);
  return rc;
 }
--
2.9.3


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [cifs-utils PATCH v3 0/4] cifs.upcall: allow cifs.upcall to scrape cache location initiating task's environment

Simo Sorce-3
In reply to this post by Jeff Layton-4
On Wed, 2017-02-15 at 11:15 -0500, Jeff Layton wrote:

> Apologies for v3 series, I had some extra patches in there. This is
> the one that should have been sent. Relabeled as v4 for clarity.
>
> Third respin of this series. Reordered for better safety for bisecting.
> The environment scraping is now on by default, but can be disabled with
> "-E" in environments where it's not needed.
>
> Also, I've added a patch to make cifs.upcall drop capabilities before
> doing most of its work. This may help reduce the attack surface of the
> program.
>
> Jeff Layton (4):
>   cifs.upcall: convert two flags from int to bool
>   cifs.upcall: switch group IDs when handling an upcall
>   cifs.upcall: drop capabilities early in program
>   cifs.upcall: allow scraping of KRB5CCNAME out of initiating task's
>     /proc/<pid>/environ file
>
>  Makefile.am      |   2 +-
>  cifs.upcall.8.in |   9 ++
>  cifs.upcall.c    | 255 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
>  3 files changed, 256 insertions(+), 10 deletions(-)
>

You can add a reviewed-by with my name.

Simo.

--
Simo Sorce * Red Hat, Inc * New York


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: problem when testing recent cifs.upcall

Jeff Layton-4
In reply to this post by Jeff Layton-4
On Thu, 2017-02-23 at 14:18 -0600, Chad William Seys wrote:

> > To be clear...I assume that you have a keytab set up someplace that
> > has the smbadmin@ credentials in it, correct? That's the only way
> > that cifs.upcall would instantiate a new credcache.
>
> Right.  smbadmin@ credentials are in /etc/krb5.keytab.  'mount' must
> check there by default.
>
> > It sounds like you're walking into the DFS mount in a task that is
> > running as root, but that has inherited a KRB5CCNAME environment
> > variable from a cwseys@ login session.
>
> The task that is walking into the DFS mount is running as 'cwseys' .  My
> guess is that when cwseys tries to cd into DFS mount, cifs.upcall or the
> kernel is using the wrong name for root's credential cache.
>
> > It might be nice to see the debug level output from syslog, so we can
> > tell what's actually happening in the upcall. Can you provide that?
>
>
> cwseys:
> $ kdestroy
> $ cd /
>
> root:
> # umount /smb
> # umount /smb  # to be sure!
> # kdestroy
> #  ls /tmp/krb5cc_* -al
> ls: cannot access '/tmp/krb5cc_*': No such file or directory
>
> cwseys:
> $ kinit
> Password for [hidden email]:
> $ ls /tmp/krb5cc_* -al
> -rw------- 1 cwseys cwseys 939 Feb 23 12:59 /tmp/krb5cc_1494_sM11PG
>
> $ klist -c /tmp/krb5cc_1494_sM11PG
> Ticket cache: FILE:/tmp/krb5cc_1494_sM11PG
> Default principal: [hidden email]
>
> Valid starting       Expires              Service principal
> 02/23/2017 12:59:00  03/05/2017 12:58:57
> krbtgt/[hidden email]
>
>
> root:
> # mount -t cifs //smb.physics.wisc.edu/smb /smb
> -osec=krb5,multiuser,username=[hidden email] --verbose
> mount.cifs kernel mount options:
> ip=128.104.160.17,unc=\\smb.physics.wisc.edu\smb,sec=krb5,multiuser,user=[hidden email],pass=********
>
> #  ls /tmp/krb5cc_* -al
> -rw------- 1 root   root   1046 Feb 23 13:00 /tmp/krb5cc_0
> -rw------- 1 cwseys cwseys  939 Feb 23 12:59 /tmp/krb5cc_1494_sM11PG
>
> # klist -c /tmp/krb5cc_0
> Ticket cache: FILE:/tmp/krb5cc_0
> Default principal: [hidden email]
>
> Valid starting       Expires              Service principal
> 02/23/2017 13:00:01  03/05/2017 13:00:01
> krbtgt/[hidden email]
> 02/23/2017 13:00:01  03/05/2017 13:00:01
> cifs/[hidden email]
>
> [debug.log after mount]
> Feb 23 13:00:01 trog cifs.upcall: key description:
> cifs.spnego;0;0;39010000;ver=0x2;host=smb.physics.wisc.edu;ip4=128.104.160
> .17;sec=krb5;uid=0x0;creduid=0x0;user=[hidden email];pid=0x6abf
> Feb 23 13:00:01 trog cifs.upcall: ver=2
> Feb 23 13:00:01 trog cifs.upcall: host=smb.physics.wisc.edu
> Feb 23 13:00:01 trog cifs.upcall: ip=128.104.160.17
> Feb 23 13:00:01 trog cifs.upcall: sec=1
> Feb 23 13:00:01 trog cifs.upcall: uid=0
> Feb 23 13:00:01 trog cifs.upcall: creduid=0
> Feb 23 13:00:01 trog cifs.upcall: user=[hidden email]
> Feb 23 13:00:01 trog cifs.upcall: pid=27327
> Feb 23 13:00:01 trog cifs.upcall: get_cachename_from_process_env:
> pathname=/proc/27327/environ
> Feb 23 13:00:01 trog cifs.upcall: get_existing_cc: default ccache is
> FILE:/tmp/krb5cc_0
> Feb 23 13:00:01 trog cifs.upcall: get_tgt_time: unable to get principal
> Feb 23 13:00:01 trog cifs.upcall: handle_krb5_mech: getting service
> ticket for smb.physics.wisc.edu
> Feb 23 13:00:01 trog cifs.upcall: handle_krb5_mech: obtained service ticket
> Feb 23 13:00:01 trog cifs.upcall: Exit status 0
> Feb 23 13:00:01 trog cifs.upcall: key description:
> cifs.spnego;0;0;39010000;ver=0x2;host=smb.physics.wisc.edu;ip4=128.104.160.17;sec=krb5;uid=0x0;creduid=0x0;user=[hidden email];pid=0x6abf
> Feb 23 13:00:01 trog cifs.upcall: ver=2
> Feb 23 13:00:01 trog cifs.upcall: host=smb.physics.wisc.edu
> Feb 23 13:00:01 trog cifs.upcall: ip=128.104.160.17
> Feb 23 13:00:01 trog cifs.upcall: sec=1
> Feb 23 13:00:01 trog cifs.upcall: uid=0
> Feb 23 13:00:01 trog cifs.upcall: creduid=0
> Feb 23 13:00:01 trog cifs.upcall: user=[hidden email]
> Feb 23 13:00:01 trog cifs.upcall: pid=27327
> Feb 23 13:00:01 trog cifs.upcall: get_cachename_from_process_env:
> pathname=/proc/27327/environ
> Feb 23 13:00:01 trog cifs.upcall: get_existing_cc: default ccache is
> FILE:/tmp/krb5cc_0
> Feb 23 13:00:01 trog cifs.upcall: handle_krb5_mech: getting service
> ticket for smb.physics.wisc.edu
> Feb 23 13:00:01 trog cifs.upcall: handle_krb5_mech: obtained service ticket
> Feb 23 13:00:01 trog cifs.upcall: Exit status 0
> Feb 23 13:00:01 trog cifs.upcall: key description:
> cifs.spnego;0;0;39010000;ver=0x2;host=smb.physics.wisc.edu;ip4=128.104.160.17;sec=krb5;uid=0x5d6;creduid=0x5d6;pid=0x6725
> Feb 23 13:00:01 trog cifs.upcall: ver=2
> Feb 23 13:00:01 trog cifs.upcall: host=smb.physics.wisc.edu
> Feb 23 13:00:01 trog cifs.upcall: ip=128.104.160.17
> Feb 23 13:00:01 trog cifs.upcall: sec=1
> Feb 23 13:00:01 trog cifs.upcall: uid=1494
> Feb 23 13:00:01 trog cifs.upcall: creduid=1494
> Feb 23 13:00:01 trog cifs.upcall: pid=26405
> Feb 23 13:00:01 trog cifs.upcall: get_cachename_from_process_env:
> pathname=/proc/26405/environ
> Feb 23 13:00:01 trog cifs.upcall: get_cachename_from_process_env:
> cachename = FILE:/tmp/krb5cc_1494_bkfO2z
> Feb 23 13:00:01 trog cifs.upcall: get_existing_cc: default ccache is
> FILE:/tmp/krb5cc_1494_bkfO2z
> Feb 23 13:00:01 trog cifs.upcall: get_tgt_time: unable to get principal
> Feb 23 13:00:01 trog cifs.upcall: Exit status 1
>
> cwseys:
> $ cd /smb
>
> [debug.log after cd /smb]
> Feb 23 13:05:20 trog cifs.upcall: key description:
> cifs.spnego;0;0;39010000;ver=0x2;host=smb.physics.wisc.edu;ip4=128.104.160.17;sec=krb5;uid=0x5d6;creduid=0x5d6;pid=0x3397
> Feb 23 13:05:20 trog cifs.upcall: ver=2
> Feb 23 13:05:20 trog cifs.upcall: host=smb.physics.wisc.edu
> Feb 23 13:05:20 trog cifs.upcall: ip=128.104.160.17
> Feb 23 13:05:20 trog cifs.upcall: sec=1
> Feb 23 13:05:20 trog cifs.upcall: uid=1494
> Feb 23 13:05:20 trog cifs.upcall: creduid=1494
> Feb 23 13:05:20 trog cifs.upcall: pid=13207
> Feb 23 13:05:20 trog cifs.upcall: get_cachename_from_process_env:
> pathname=/proc/13207/environ
> Feb 23 13:05:20 trog cifs.upcall: get_cachename_from_process_env:
> cachename = FILE:/tmp/krb5cc_1494_sM11PG
> Feb 23 13:05:20 trog cifs.upcall: get_existing_cc: default ccache is
> FILE:/tmp/krb5cc_1494_sM11PG
> Feb 23 13:05:20 trog cifs.upcall: handle_krb5_mech: getting service
> ticket for smb.physics.wisc.edu
> Feb 23 13:05:20 trog cifs.upcall: handle_krb5_mech: obtained service ticket
> Feb 23 13:05:20 trog cifs.upcall: Exit status 0
>
> $ kdestroy
> $ ls /tmp/krb5cc_* -al
> -rw------- 1 root root 1046 Feb 23 13:00 /tmp/krb5cc_0
>
> # obs-cos is on a different server - DFS linked.
> $ cd obs-cos
> $ ls
> ls: cannot open directory '.': Permission denied
>
> # kerberos cache file created with root owner/group !
> # The file has bytes in it, but not matching the size above. Wonder
> # what's in it... ?
> $ ls /tmp/krb5cc_* -al
> -rw------- 1 root root 1046 Feb 23 13:00 /tmp/krb5cc_0
> -rw------- 1 root root 1050 Feb 23 13:05 /tmp/krb5cc_1494_sM11PG
>
> # now cannot kinit
> $ kinit
> Password for [hidden email]:
> kinit: Failed to store credentials: Internal credentials cache error
> (filename: /tmp/krb5cc_1494_sM11PG) while getting initial credentials
>
> root:
> # lets look in the credential cache that was created by root.
> # looks like credentials used by root to mount /smb:
> # My guess is the kernel was trying to stash the
> # cifs/[hidden email]
> # kerberos ticket, but put it in krb5cc_1494_sM11PG instead
> # of krb5cc_0
> # klist -c /tmp/krb5cc_1494_sM11PG
> Ticket cache: FILE:/tmp/krb5cc_1494_sM11PG
> Default principal: [hidden email]
>
> Valid starting       Expires              Service principal
> 02/23/2017 13:05:59  03/05/2017 13:05:59
> krbtgt/[hidden email]
> 02/23/2017 13:05:59  03/05/2017 13:05:59
> cifs/[hidden email]
>
> # klist -c /tmp/krb5cc_0
> Ticket cache: FILE:/tmp/krb5cc_0
> Default principal: [hidden email]
>
> Valid starting       Expires              Service principal
> 02/23/2017 13:00:01  03/05/2017 13:00:01
> krbtgt/[hidden email]
> 02/23/2017 13:00:01  03/05/2017 13:00:01
> cifs/[hidden email]
>
> [debug.log after trying to cd obs-cos]
> vvvvvvvvvvvvvvvvvvvvvvvvvvvv
> I think the error is here:  Notice pid=13207, that belongs
> to cwseys but cifs.upcall key description is trying to use uid=0 and
> creduid=0 . The credential cache file is correct, but the uid/creduid
> are not.
>
> cwseys   13207 /bin/bash
>
> Also, in the above the log from 'cd /smb' cifs.upcall used  uid=1494 and
> creduid=1494 .
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^
>

Yep, that's clearly the issue. The question is how you're ending up in
that situation...

Regardless of how it's happening to you, it's probably possible to fool
the environment scraping like this, by triggering a krb5 upcall from
the context of a setuid program that has inherited the KRB5CCNAME
environment variable from an unprivileged process.

I'm not sure what we can reasonably do about that. I suppose it might
be interesting to dump the Uid: line from /proc/pid/status when we do
this upcall, and see what all of the values are set to. Maybe we can
reject using the credcache if the uid in the upcall doesn't match one
of the values?

I'll see if I can cook up a debug patch sometime soon for that.

> Feb 23 13:05:59 trog cifs.upcall: key description:
> cifs.spnego;0;0;39010000;ver=0x2;host=smb02.physics.wisc.edu;ip4=128.104.164.79;sec=krb5;uid=0x0;creduid=0x0;user=[hidden email];pid=0x3397
> Feb 23 13:05:59 trog cifs.upcall: ver=2
> Feb 23 13:05:59 trog cifs.upcall: host=smb02.physics.wisc.edu
> Feb 23 13:05:59 trog cifs.upcall: ip=128.104.164.79
> Feb 23 13:05:59 trog cifs.upcall: sec=1
> Feb 23 13:05:59 trog cifs.upcall: uid=0
> Feb 23 13:05:59 trog cifs.upcall: creduid=0
> Feb 23 13:05:59 trog cifs.upcall: user=[hidden email]
> Feb 23 13:05:59 trog cifs.upcall: pid=13207
> Feb 23 13:05:59 trog cifs.upcall: get_cachename_from_process_env:
> pathname=/proc/13207/environ
> Feb 23 13:05:59 trog cifs.upcall: get_cachename_from_process_env:
> cachename = FILE:/tmp/krb5cc_1494_sM11PG
> Feb 23 13:05:59 trog cifs.upcall: get_existing_cc: default ccache is
> FILE:/tmp/krb5cc_1494_sM11PG
> Feb 23 13:05:59 trog cifs.upcall: get_tgt_time: unable to get principal
> Feb 23 13:05:59 trog cifs.upcall: handle_krb5_mech: getting service
> ticket for smb02.physics.wisc.edu
> Feb 23 13:05:59 trog cifs.upcall: handle_krb5_mech: obtained service ticket
> Feb 23 13:05:59 trog cifs.upcall: Exit status 0
> Feb 23 13:05:59 trog cifs.upcall: key description:
> cifs.spnego;0;0;39010000;ver=0x2;host=smb02.physics.wisc.edu;ip4=128.104.164.79;sec=krb5;uid=0x5d6;creduid=0x5d6;pid=0x6725
> Feb 23 13:05:59 trog cifs.upcall: ver=2
> Feb 23 13:05:59 trog cifs.upcall: host=smb02.physics.wisc.edu
> Feb 23 13:05:59 trog cifs.upcall: ip=128.104.164.79
> Feb 23 13:05:59 trog cifs.upcall: sec=1
> Feb 23 13:05:59 trog cifs.upcall: uid=1494
> Feb 23 13:05:59 trog cifs.upcall: creduid=1494
> Feb 23 13:05:59 trog cifs.upcall: pid=26405
> Feb 23 13:05:59 trog cifs.upcall: get_cachename_from_process_env:
> pathname=/proc/26405/environ
> Feb 23 13:05:59 trog cifs.upcall: get_cachename_from_process_env:
> cachename = FILE:/tmp/krb5cc_1494_bkfO2z
> Feb 23 13:05:59 trog cifs.upcall: get_existing_cc: default ccache is
> FILE:/tmp/krb5cc_1494_bkfO2z
> Feb 23 13:05:59 trog cifs.upcall: get_tgt_time: unable to get principal
> Feb 23 13:05:59 trog cifs.upcall: Exit status 1
> Feb 23 13:06:03 trog cifs.upcall: key description:
> cifs.spnego;0;0;39010000;ver=0x2;host=smb02.physics.wisc.edu;ip4=128.104.164.79;sec=krb5;uid=0x5d6;creduid=0x5d6;pid=0x6ba0
> Feb 23 13:06:03 trog cifs.upcall: ver=2
> Feb 23 13:06:03 trog cifs.upcall: host=smb02.physics.wisc.edu
> Feb 23 13:06:03 trog cifs.upcall: ip=128.104.164.79
> Feb 23 13:06:03 trog cifs.upcall: sec=1
> Feb 23 13:06:03 trog cifs.upcall: uid=1494
> Feb 23 13:06:03 trog cifs.upcall: creduid=1494
> Feb 23 13:06:03 trog cifs.upcall: pid=27552
> Feb 23 13:06:03 trog cifs.upcall: get_cachename_from_process_env:
> pathname=/proc/27552/environ
> Feb 23 13:06:03 trog cifs.upcall: get_cachename_from_process_env:
> cachename = FILE:/tmp/krb5cc_1494_sM11PG
> Feb 23 13:06:03 trog cifs.upcall: get_existing_cc: default ccache is
> FILE:/tmp/krb5cc_1494_sM11PG
> Feb 23 13:06:03 trog cifs.upcall: get_tgt_time: unable to get principal
> Feb 23 13:06:03 trog cifs.upcall: Exit status 1
>
> Thanks for your work!
> Chad.

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: problem when testing recent cifs.upcall

Jeff Layton-3
On Thu, 2017-02-23 at 16:10 -0500, Jeff Layton wrote:

> On Thu, 2017-02-23 at 14:18 -0600, Chad William Seys wrote:
> > > To be clear...I assume that you have a keytab set up someplace that
> > > has the smbadmin@ credentials in it, correct? That's the only way
> > > that cifs.upcall would instantiate a new credcache.
> >
> > Right.  smbadmin@ credentials are in /etc/krb5.keytab.  'mount' must
> > check there by default.
> >
> > > It sounds like you're walking into the DFS mount in a task that is
> > > running as root, but that has inherited a KRB5CCNAME environment
> > > variable from a cwseys@ login session.
> >
> > The task that is walking into the DFS mount is running as 'cwseys' .  My
> > guess is that when cwseys tries to cd into DFS mount, cifs.upcall or the
> > kernel is using the wrong name for root's credential cache.
> >
> > > It might be nice to see the debug level output from syslog, so we can
> > > tell what's actually happening in the upcall. Can you provide that?
> >
> >
> > cwseys:
> > $ kdestroy
> > $ cd /
> >
> > root:
> > # umount /smb
> > # umount /smb  # to be sure!
> > # kdestroy
> > #  ls /tmp/krb5cc_* -al
> > ls: cannot access '/tmp/krb5cc_*': No such file or directory
> >
> > cwseys:
> > $ kinit
> > Password for [hidden email]:
> > $ ls /tmp/krb5cc_* -al
> > -rw------- 1 cwseys cwseys 939 Feb 23 12:59 /tmp/krb5cc_1494_sM11PG
> >
> > $ klist -c /tmp/krb5cc_1494_sM11PG
> > Ticket cache: FILE:/tmp/krb5cc_1494_sM11PG
> > Default principal: [hidden email]
> >
> > Valid starting       Expires              Service principal
> > 02/23/2017 12:59:00  03/05/2017 12:58:57
> > krbtgt/[hidden email]
> >
> >
> > root:
> > # mount -t cifs //smb.physics.wisc.edu/smb /smb
> > -osec=krb5,multiuser,username=[hidden email] --verbose
> > mount.cifs kernel mount options:
> > ip=128.104.160.17,unc=\\smb.physics.wisc.edu\smb,sec=krb5,multiuser,user=[hidden email],pass=********
> >
> > #  ls /tmp/krb5cc_* -al
> > -rw------- 1 root   root   1046 Feb 23 13:00 /tmp/krb5cc_0
> > -rw------- 1 cwseys cwseys  939 Feb 23 12:59 /tmp/krb5cc_1494_sM11PG
> >
> > # klist -c /tmp/krb5cc_0
> > Ticket cache: FILE:/tmp/krb5cc_0
> > Default principal: [hidden email]
> >
> > Valid starting       Expires              Service principal
> > 02/23/2017 13:00:01  03/05/2017 13:00:01
> > krbtgt/[hidden email]
> > 02/23/2017 13:00:01  03/05/2017 13:00:01
> > cifs/[hidden email]
> >
> > [debug.log after mount]
> > Feb 23 13:00:01 trog cifs.upcall: key description:
> > cifs.spnego;0;0;39010000;ver=0x2;host=smb.physics.wisc.edu;ip4=128.104.160
> > .17;sec=krb5;uid=0x0;creduid=0x0;user=[hidden email];pid=0x6abf
> > Feb 23 13:00:01 trog cifs.upcall: ver=2
> > Feb 23 13:00:01 trog cifs.upcall: host=smb.physics.wisc.edu
> > Feb 23 13:00:01 trog cifs.upcall: ip=128.104.160.17
> > Feb 23 13:00:01 trog cifs.upcall: sec=1
> > Feb 23 13:00:01 trog cifs.upcall: uid=0
> > Feb 23 13:00:01 trog cifs.upcall: creduid=0
> > Feb 23 13:00:01 trog cifs.upcall: user=[hidden email]
> > Feb 23 13:00:01 trog cifs.upcall: pid=27327
> > Feb 23 13:00:01 trog cifs.upcall: get_cachename_from_process_env:
> > pathname=/proc/27327/environ
> > Feb 23 13:00:01 trog cifs.upcall: get_existing_cc: default ccache is
> > FILE:/tmp/krb5cc_0
> > Feb 23 13:00:01 trog cifs.upcall: get_tgt_time: unable to get principal
> > Feb 23 13:00:01 trog cifs.upcall: handle_krb5_mech: getting service
> > ticket for smb.physics.wisc.edu
> > Feb 23 13:00:01 trog cifs.upcall: handle_krb5_mech: obtained service ticket
> > Feb 23 13:00:01 trog cifs.upcall: Exit status 0
> > Feb 23 13:00:01 trog cifs.upcall: key description:
> > cifs.spnego;0;0;39010000;ver=0x2;host=smb.physics.wisc.edu;ip4=128.104.160.17;sec=krb5;uid=0x0;creduid=0x0;user=[hidden email];pid=0x6abf
> > Feb 23 13:00:01 trog cifs.upcall: ver=2
> > Feb 23 13:00:01 trog cifs.upcall: host=smb.physics.wisc.edu
> > Feb 23 13:00:01 trog cifs.upcall: ip=128.104.160.17
> > Feb 23 13:00:01 trog cifs.upcall: sec=1
> > Feb 23 13:00:01 trog cifs.upcall: uid=0
> > Feb 23 13:00:01 trog cifs.upcall: creduid=0
> > Feb 23 13:00:01 trog cifs.upcall: user=[hidden email]
> > Feb 23 13:00:01 trog cifs.upcall: pid=27327
> > Feb 23 13:00:01 trog cifs.upcall: get_cachename_from_process_env:
> > pathname=/proc/27327/environ
> > Feb 23 13:00:01 trog cifs.upcall: get_existing_cc: default ccache is
> > FILE:/tmp/krb5cc_0
> > Feb 23 13:00:01 trog cifs.upcall: handle_krb5_mech: getting service
> > ticket for smb.physics.wisc.edu
> > Feb 23 13:00:01 trog cifs.upcall: handle_krb5_mech: obtained service ticket
> > Feb 23 13:00:01 trog cifs.upcall: Exit status 0
> > Feb 23 13:00:01 trog cifs.upcall: key description:
> > cifs.spnego;0;0;39010000;ver=0x2;host=smb.physics.wisc.edu;ip4=128.104.160.17;sec=krb5;uid=0x5d6;creduid=0x5d6;pid=0x6725
> > Feb 23 13:00:01 trog cifs.upcall: ver=2
> > Feb 23 13:00:01 trog cifs.upcall: host=smb.physics.wisc.edu
> > Feb 23 13:00:01 trog cifs.upcall: ip=128.104.160.17
> > Feb 23 13:00:01 trog cifs.upcall: sec=1
> > Feb 23 13:00:01 trog cifs.upcall: uid=1494
> > Feb 23 13:00:01 trog cifs.upcall: creduid=1494
> > Feb 23 13:00:01 trog cifs.upcall: pid=26405
> > Feb 23 13:00:01 trog cifs.upcall: get_cachename_from_process_env:
> > pathname=/proc/26405/environ
> > Feb 23 13:00:01 trog cifs.upcall: get_cachename_from_process_env:
> > cachename = FILE:/tmp/krb5cc_1494_bkfO2z
> > Feb 23 13:00:01 trog cifs.upcall: get_existing_cc: default ccache is
> > FILE:/tmp/krb5cc_1494_bkfO2z
> > Feb 23 13:00:01 trog cifs.upcall: get_tgt_time: unable to get principal
> > Feb 23 13:00:01 trog cifs.upcall: Exit status 1
> >
> > cwseys:
> > $ cd /smb
> >
> > [debug.log after cd /smb]
> > Feb 23 13:05:20 trog cifs.upcall: key description:
> > cifs.spnego;0;0;39010000;ver=0x2;host=smb.physics.wisc.edu;ip4=128.104.160.17;sec=krb5;uid=0x5d6;creduid=0x5d6;pid=0x3397
> > Feb 23 13:05:20 trog cifs.upcall: ver=2
> > Feb 23 13:05:20 trog cifs.upcall: host=smb.physics.wisc.edu
> > Feb 23 13:05:20 trog cifs.upcall: ip=128.104.160.17
> > Feb 23 13:05:20 trog cifs.upcall: sec=1
> > Feb 23 13:05:20 trog cifs.upcall: uid=1494
> > Feb 23 13:05:20 trog cifs.upcall: creduid=1494
> > Feb 23 13:05:20 trog cifs.upcall: pid=13207
> > Feb 23 13:05:20 trog cifs.upcall: get_cachename_from_process_env:
> > pathname=/proc/13207/environ
> > Feb 23 13:05:20 trog cifs.upcall: get_cachename_from_process_env:
> > cachename = FILE:/tmp/krb5cc_1494_sM11PG
> > Feb 23 13:05:20 trog cifs.upcall: get_existing_cc: default ccache is
> > FILE:/tmp/krb5cc_1494_sM11PG
> > Feb 23 13:05:20 trog cifs.upcall: handle_krb5_mech: getting service
> > ticket for smb.physics.wisc.edu
> > Feb 23 13:05:20 trog cifs.upcall: handle_krb5_mech: obtained service ticket
> > Feb 23 13:05:20 trog cifs.upcall: Exit status 0
> >
> > $ kdestroy
> > $ ls /tmp/krb5cc_* -al
> > -rw------- 1 root root 1046 Feb 23 13:00 /tmp/krb5cc_0
> >
> > # obs-cos is on a different server - DFS linked.
> > $ cd obs-cos
> > $ ls
> > ls: cannot open directory '.': Permission denied
> >
> > # kerberos cache file created with root owner/group !
> > # The file has bytes in it, but not matching the size above. Wonder
> > # what's in it... ?
> > $ ls /tmp/krb5cc_* -al
> > -rw------- 1 root root 1046 Feb 23 13:00 /tmp/krb5cc_0
> > -rw------- 1 root root 1050 Feb 23 13:05 /tmp/krb5cc_1494_sM11PG
> >
> > # now cannot kinit
> > $ kinit
> > Password for [hidden email]:
> > kinit: Failed to store credentials: Internal credentials cache error
> > (filename: /tmp/krb5cc_1494_sM11PG) while getting initial credentials
> >
> > root:
> > # lets look in the credential cache that was created by root.
> > # looks like credentials used by root to mount /smb:
> > # My guess is the kernel was trying to stash the
> > # cifs/[hidden email]
> > # kerberos ticket, but put it in krb5cc_1494_sM11PG instead
> > # of krb5cc_0
> > # klist -c /tmp/krb5cc_1494_sM11PG
> > Ticket cache: FILE:/tmp/krb5cc_1494_sM11PG
> > Default principal: [hidden email]
> >
> > Valid starting       Expires              Service principal
> > 02/23/2017 13:05:59  03/05/2017 13:05:59
> > krbtgt/[hidden email]
> > 02/23/2017 13:05:59  03/05/2017 13:05:59
> > cifs/[hidden email]
> >
> > # klist -c /tmp/krb5cc_0
> > Ticket cache: FILE:/tmp/krb5cc_0
> > Default principal: [hidden email]
> >
> > Valid starting       Expires              Service principal
> > 02/23/2017 13:00:01  03/05/2017 13:00:01
> > krbtgt/[hidden email]
> > 02/23/2017 13:00:01  03/05/2017 13:00:01
> > cifs/[hidden email]
> >
> > [debug.log after trying to cd obs-cos]
> > vvvvvvvvvvvvvvvvvvvvvvvvvvvv
> > I think the error is here:  Notice pid=13207, that belongs
> > to cwseys but cifs.upcall key description is trying to use uid=0 and
> > creduid=0 . The credential cache file is correct, but the uid/creduid
> > are not.
> >
> > cwseys   13207 /bin/bash
> >
> > Also, in the above the log from 'cd /smb' cifs.upcall used  uid=1494 and
> > creduid=1494 .
> > ^^^^^^^^^^^^^^^^^^^^^^^^^^^
> >
>
> Yep, that's clearly the issue. The question is how you're ending up in
> that situation...
>
> Regardless of how it's happening to you, it's probably possible to fool
> the environment scraping like this, by triggering a krb5 upcall from
> the context of a setuid program that has inherited the KRB5CCNAME
> environment variable from an unprivileged process.
>
> I'm not sure what we can reasonably do about that. I suppose it might
> be interesting to dump the Uid: line from /proc/pid/status when we do
> this upcall, and see what all of the values are set to. Maybe we can
> reject using the credcache if the uid in the upcall doesn't match one
> of the values?
>
> I'll see if I can cook up a debug patch sometime soon for that.
>

Just out of curiousity. As that unprivileged user, what do you get back
 if you do this?

    $ which cd ; ls -l `which cd`

Thanks,
--
Jeff Layton <[hidden email]>

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: problem when testing recent cifs.upcall

Jeff Layton-4
On Thu, 2017-02-23 at 16:30 -0500, Jeff Layton wrote:

> On Thu, 2017-02-23 at 16:10 -0500, Jeff Layton wrote:
> > On Thu, 2017-02-23 at 14:18 -0600, Chad William Seys wrote:
> > > > To be clear...I assume that you have a keytab set up someplace that
> > > > has the smbadmin@ credentials in it, correct? That's the only way
> > > > that cifs.upcall would instantiate a new credcache.
> > >
> > > Right.  smbadmin@ credentials are in /etc/krb5.keytab.  'mount' must
> > > check there by default.
> > >
> > > > It sounds like you're walking into the DFS mount in a task that is
> > > > running as root, but that has inherited a KRB5CCNAME environment
> > > > variable from a cwseys@ login session.
> > >
> > > The task that is walking into the DFS mount is running as 'cwseys' .  My
> > > guess is that when cwseys tries to cd into DFS mount, cifs.upcall or the
> > > kernel is using the wrong name for root's credential cache.
> > >
> > > > It might be nice to see the debug level output from syslog, so we can
> > > > tell what's actually happening in the upcall. Can you provide that?
> > >
> > >
> > > cwseys:
> > > $ kdestroy
> > > $ cd /
> > >
> > > root:
> > > # umount /smb
> > > # umount /smb  # to be sure!
> > > # kdestroy
> > > #  ls /tmp/krb5cc_* -al
> > > ls: cannot access '/tmp/krb5cc_*': No such file or directory
> > >
> > > cwseys:
> > > $ kinit
> > > Password for [hidden email]:
> > > $ ls /tmp/krb5cc_* -al
> > > -rw------- 1 cwseys cwseys 939 Feb 23 12:59 /tmp/krb5cc_1494_sM11PG
> > >
> > > $ klist -c /tmp/krb5cc_1494_sM11PG
> > > Ticket cache: FILE:/tmp/krb5cc_1494_sM11PG
> > > Default principal: [hidden email]
> > >
> > > Valid starting       Expires              Service principal
> > > 02/23/2017 12:59:00  03/05/2017 12:58:57
> > > krbtgt/[hidden email]
> > >
> > >
> > > root:
> > > # mount -t cifs //smb.physics.wisc.edu/smb /smb
> > > -osec=krb5,multiuser,username=[hidden email] --verbose
> > > mount.cifs kernel mount options:
> > > ip=128.104.160.17,unc=\\smb.physics.wisc.edu\smb,sec=krb5,multiuser,user=[hidden email],pass=********
> > >
> > > #  ls /tmp/krb5cc_* -al
> > > -rw------- 1 root   root   1046 Feb 23 13:00 /tmp/krb5cc_0
> > > -rw------- 1 cwseys cwseys  939 Feb 23 12:59 /tmp/krb5cc_1494_sM11PG
> > >
> > > # klist -c /tmp/krb5cc_0
> > > Ticket cache: FILE:/tmp/krb5cc_0
> > > Default principal: [hidden email]
> > >
> > > Valid starting       Expires              Service principal
> > > 02/23/2017 13:00:01  03/05/2017 13:00:01
> > > krbtgt/[hidden email]
> > > 02/23/2017 13:00:01  03/05/2017 13:00:01
> > > cifs/[hidden email]
> > >
> > > [debug.log after mount]
> > > Feb 23 13:00:01 trog cifs.upcall: key description:
> > > cifs.spnego;0;0;39010000;ver=0x2;host=smb.physics.wisc.edu;ip4=128.104.160
> > > .17;sec=krb5;uid=0x0;creduid=0x0;user=[hidden email];pid=0x6abf
> > > Feb 23 13:00:01 trog cifs.upcall: ver=2
> > > Feb 23 13:00:01 trog cifs.upcall: host=smb.physics.wisc.edu
> > > Feb 23 13:00:01 trog cifs.upcall: ip=128.104.160.17
> > > Feb 23 13:00:01 trog cifs.upcall: sec=1
> > > Feb 23 13:00:01 trog cifs.upcall: uid=0
> > > Feb 23 13:00:01 trog cifs.upcall: creduid=0
> > > Feb 23 13:00:01 trog cifs.upcall: user=[hidden email]
> > > Feb 23 13:00:01 trog cifs.upcall: pid=27327
> > > Feb 23 13:00:01 trog cifs.upcall: get_cachename_from_process_env:
> > > pathname=/proc/27327/environ
> > > Feb 23 13:00:01 trog cifs.upcall: get_existing_cc: default ccache is
> > > FILE:/tmp/krb5cc_0
> > > Feb 23 13:00:01 trog cifs.upcall: get_tgt_time: unable to get principal
> > > Feb 23 13:00:01 trog cifs.upcall: handle_krb5_mech: getting service
> > > ticket for smb.physics.wisc.edu
> > > Feb 23 13:00:01 trog cifs.upcall: handle_krb5_mech: obtained service ticket
> > > Feb 23 13:00:01 trog cifs.upcall: Exit status 0
> > > Feb 23 13:00:01 trog cifs.upcall: key description:
> > > cifs.spnego;0;0;39010000;ver=0x2;host=smb.physics.wisc.edu;ip4=128.104.160.17;sec=krb5;uid=0x0;creduid=0x0;user=[hidden email];pid=0x6abf
> > > Feb 23 13:00:01 trog cifs.upcall: ver=2
> > > Feb 23 13:00:01 trog cifs.upcall: host=smb.physics.wisc.edu
> > > Feb 23 13:00:01 trog cifs.upcall: ip=128.104.160.17
> > > Feb 23 13:00:01 trog cifs.upcall: sec=1
> > > Feb 23 13:00:01 trog cifs.upcall: uid=0
> > > Feb 23 13:00:01 trog cifs.upcall: creduid=0
> > > Feb 23 13:00:01 trog cifs.upcall: user=[hidden email]
> > > Feb 23 13:00:01 trog cifs.upcall: pid=27327
> > > Feb 23 13:00:01 trog cifs.upcall: get_cachename_from_process_env:
> > > pathname=/proc/27327/environ
> > > Feb 23 13:00:01 trog cifs.upcall: get_existing_cc: default ccache is
> > > FILE:/tmp/krb5cc_0
> > > Feb 23 13:00:01 trog cifs.upcall: handle_krb5_mech: getting service
> > > ticket for smb.physics.wisc.edu
> > > Feb 23 13:00:01 trog cifs.upcall: handle_krb5_mech: obtained service ticket
> > > Feb 23 13:00:01 trog cifs.upcall: Exit status 0
> > > Feb 23 13:00:01 trog cifs.upcall: key description:
> > > cifs.spnego;0;0;39010000;ver=0x2;host=smb.physics.wisc.edu;ip4=128.104.160.17;sec=krb5;uid=0x5d6;creduid=0x5d6;pid=0x6725
> > > Feb 23 13:00:01 trog cifs.upcall: ver=2
> > > Feb 23 13:00:01 trog cifs.upcall: host=smb.physics.wisc.edu
> > > Feb 23 13:00:01 trog cifs.upcall: ip=128.104.160.17
> > > Feb 23 13:00:01 trog cifs.upcall: sec=1
> > > Feb 23 13:00:01 trog cifs.upcall: uid=1494
> > > Feb 23 13:00:01 trog cifs.upcall: creduid=1494
> > > Feb 23 13:00:01 trog cifs.upcall: pid=26405
> > > Feb 23 13:00:01 trog cifs.upcall: get_cachename_from_process_env:
> > > pathname=/proc/26405/environ
> > > Feb 23 13:00:01 trog cifs.upcall: get_cachename_from_process_env:
> > > cachename = FILE:/tmp/krb5cc_1494_bkfO2z
> > > Feb 23 13:00:01 trog cifs.upcall: get_existing_cc: default ccache is
> > > FILE:/tmp/krb5cc_1494_bkfO2z
> > > Feb 23 13:00:01 trog cifs.upcall: get_tgt_time: unable to get principal
> > > Feb 23 13:00:01 trog cifs.upcall: Exit status 1
> > >
> > > cwseys:
> > > $ cd /smb
> > >
> > > [debug.log after cd /smb]
> > > Feb 23 13:05:20 trog cifs.upcall: key description:
> > > cifs.spnego;0;0;39010000;ver=0x2;host=smb.physics.wisc.edu;ip4=128.104.160.17;sec=krb5;uid=0x5d6;creduid=0x5d6;pid=0x3397
> > > Feb 23 13:05:20 trog cifs.upcall: ver=2
> > > Feb 23 13:05:20 trog cifs.upcall: host=smb.physics.wisc.edu
> > > Feb 23 13:05:20 trog cifs.upcall: ip=128.104.160.17
> > > Feb 23 13:05:20 trog cifs.upcall: sec=1
> > > Feb 23 13:05:20 trog cifs.upcall: uid=1494
> > > Feb 23 13:05:20 trog cifs.upcall: creduid=1494
> > > Feb 23 13:05:20 trog cifs.upcall: pid=13207
> > > Feb 23 13:05:20 trog cifs.upcall: get_cachename_from_process_env:
> > > pathname=/proc/13207/environ
> > > Feb 23 13:05:20 trog cifs.upcall: get_cachename_from_process_env:
> > > cachename = FILE:/tmp/krb5cc_1494_sM11PG
> > > Feb 23 13:05:20 trog cifs.upcall: get_existing_cc: default ccache is
> > > FILE:/tmp/krb5cc_1494_sM11PG
> > > Feb 23 13:05:20 trog cifs.upcall: handle_krb5_mech: getting service
> > > ticket for smb.physics.wisc.edu
> > > Feb 23 13:05:20 trog cifs.upcall: handle_krb5_mech: obtained service ticket
> > > Feb 23 13:05:20 trog cifs.upcall: Exit status 0
> > >
> > > $ kdestroy
> > > $ ls /tmp/krb5cc_* -al
> > > -rw------- 1 root root 1046 Feb 23 13:00 /tmp/krb5cc_0
> > >
> > > # obs-cos is on a different server - DFS linked.
> > > $ cd obs-cos
> > > $ ls
> > > ls: cannot open directory '.': Permission denied
> > >
> > > # kerberos cache file created with root owner/group !
> > > # The file has bytes in it, but not matching the size above. Wonder
> > > # what's in it... ?
> > > $ ls /tmp/krb5cc_* -al
> > > -rw------- 1 root root 1046 Feb 23 13:00 /tmp/krb5cc_0
> > > -rw------- 1 root root 1050 Feb 23 13:05 /tmp/krb5cc_1494_sM11PG
> > >
> > > # now cannot kinit
> > > $ kinit
> > > Password for [hidden email]:
> > > kinit: Failed to store credentials: Internal credentials cache error
> > > (filename: /tmp/krb5cc_1494_sM11PG) while getting initial credentials
> > >
> > > root:
> > > # lets look in the credential cache that was created by root.
> > > # looks like credentials used by root to mount /smb:
> > > # My guess is the kernel was trying to stash the
> > > # cifs/[hidden email]
> > > # kerberos ticket, but put it in krb5cc_1494_sM11PG instead
> > > # of krb5cc_0
> > > # klist -c /tmp/krb5cc_1494_sM11PG
> > > Ticket cache: FILE:/tmp/krb5cc_1494_sM11PG
> > > Default principal: [hidden email]
> > >
> > > Valid starting       Expires              Service principal
> > > 02/23/2017 13:05:59  03/05/2017 13:05:59
> > > krbtgt/[hidden email]
> > > 02/23/2017 13:05:59  03/05/2017 13:05:59
> > > cifs/[hidden email]
> > >
> > > # klist -c /tmp/krb5cc_0
> > > Ticket cache: FILE:/tmp/krb5cc_0
> > > Default principal: [hidden email]
> > >
> > > Valid starting       Expires              Service principal
> > > 02/23/2017 13:00:01  03/05/2017 13:00:01
> > > krbtgt/[hidden email]
> > > 02/23/2017 13:00:01  03/05/2017 13:00:01
> > > cifs/[hidden email]
> > >
> > > [debug.log after trying to cd obs-cos]
> > > vvvvvvvvvvvvvvvvvvvvvvvvvvvv
> > > I think the error is here:  Notice pid=13207, that belongs
> > > to cwseys but cifs.upcall key description is trying to use uid=0 and
> > > creduid=0 . The credential cache file is correct, but the uid/creduid
> > > are not.
> > >
> > > cwseys   13207 /bin/bash
> > >
> > > Also, in the above the log from 'cd /smb' cifs.upcall used  uid=1494 and
> > > creduid=1494 .
> > > ^^^^^^^^^^^^^^^^^^^^^^^^^^^
> > >
> >
> > Yep, that's clearly the issue. The question is how you're ending up in
> > that situation...
> >
> > Regardless of how it's happening to you, it's probably possible to fool
> > the environment scraping like this, by triggering a krb5 upcall from
> > the context of a setuid program that has inherited the KRB5CCNAME
> > environment variable from an unprivileged process.
> >
> > I'm not sure what we can reasonably do about that. I suppose it might
> > be interesting to dump the Uid: line from /proc/pid/status when we do
> > this upcall, and see what all of the values are set to. Maybe we can
> > reject using the credcache if the uid in the upcall doesn't match one
> > of the values?
> >
> > I'll see if I can cook up a debug patch sometime soon for that.
> >
>
> Just out of curiousity. As that unprivileged user, what do you get back
>  if you do this?
>
>     $ which cd ; ls -l `which cd`
>
> Thanks,

Nevermind, I see the problem. From follow_automount in the pathwalking
code:

        old_cred = override_creds(&init_cred);
        mnt = path->dentry->d_op->d_automount(path);
        revert_creds(old_cred);

So we end up overriding the process creds in order to do the automount,
which leads to exactly this problem.

I think the best we can do here is probably to just not do the
environment scraping if the uid is 0. It's pretty hacky, but hey, we're
already in rather nasty hack territory as it is.

Thoughts?
--
Jeff Layton <[hidden email]>

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: problem when testing recent cifs.upcall

Jeff Layton-4
On Thu, 2017-02-23 at 18:46 -0500, Simo Sorce wrote:

> On Thu, 2017-02-23 at 16:42 -0500, Jeff Layton wrote:
> > On Thu, 2017-02-23 at 16:30 -0500, Jeff Layton wrote:
> > > On Thu, 2017-02-23 at 16:10 -0500, Jeff Layton wrote:
> > > > On Thu, 2017-02-23 at 14:18 -0600, Chad William Seys wrote:
> > > > > > To be clear...I assume that you have a keytab set up someplace that
> > > > > > has the smbadmin@ credentials in it, correct? That's the only way
> > > > > > that cifs.upcall would instantiate a new credcache.
> > > > >
> > > > > Right.  smbadmin@ credentials are in /etc/krb5.keytab.  'mount' must
> > > > > check there by default.
> > > > >
> > > > > > It sounds like you're walking into the DFS mount in a task that is
> > > > > > running as root, but that has inherited a KRB5CCNAME environment
> > > > > > variable from a cwseys@ login session.
> > > > >
> > > > > The task that is walking into the DFS mount is running as 'cwseys' .  My
> > > > > guess is that when cwseys tries to cd into DFS mount, cifs.upcall or the
> > > > > kernel is using the wrong name for root's credential cache.
> > > > >
> > > > > > It might be nice to see the debug level output from syslog, so we can
> > > > > > tell what's actually happening in the upcall. Can you provide that?
> > > > >
> > > > >
> > > > > cwseys:Simo.>
> > > > > > --> To unsubscribe from this list: send the line
> > > > > "unsubscribe linux-cifs" in> the body of a message to
> > > > > [hidden email]> More majordomo info at  http://vge
> > > > > r.kernel.org/majordomo-info.html
> > > > >
> > > > > $ kdestroy
> > > > > $ cd /
> > > > >
> > > > > root:
> > > > > # umount /smb
> > > > > # umount /smb  # to be sure!
> > > > > # kdestroy
> > > > > #  ls /tmp/krb5cc_* -al
> > > > > ls: cannot access '/tmp/krb5cc_*': No such file or directory
> > > > >
> > > > > cwseys:
> > > > > $ kinit
> > > > > Password for [hidden email]:
> > > > > $ ls /tmp/krb5cc_* -al
> > > > > -rw------- 1 cwseys cwseys 939 Feb 23 12:59 /tmp/krb5cc_1494_sM11PG
> > > > >
> > > > > $ klist -c /tmp/krb5cc_1494_sM11PG
> > > > > Ticket cache: FILE:/tmp/krb5cc_1494_sM11PG
> > > > > Default principal: [hidden email]
> > > > >
> > > > > Valid starting       Expires              Service principal
> > > > > 02/23/2017 12:59:00  03/05/2017 12:58:57
> > > > > krbtgt/[hidden email]
> > > > >
> > > > >
> > > > > root:
> > > > > # mount -t cifs //smb.physics.wisc.edu/smb /smb
> > > > > -osec=krb5,multiuser,username=[hidden email] --verbose
> > > > > mount.cifs kernel mount options:
> > > > > ip=128.104.160.17,unc=\\smb.physics.wisc.edu\smb,sec=krb5,multiuser,user=[hidden email],pass=********
> > > > >
> > > > > #  ls /tmp/krb5cc_* -al
> > > > > -rw------- 1 root   root   1046 Feb 23 13:00 /tmp/krb5cc_0
> > > > > -rw------- 1 cwseys cwseys  939 Feb 23 12:59 /tmp/krb5cc_1494_sM11PG
> > > > >
> > > > > # klist -c /tmp/krb5cc_0
> > > > > Ticket cache: FILE:/tmp/krb5cc_0
> > > > > Default principal: [hidden email]
> > > > >
> > > > > Valid starting       Expires              Service principal
> > > > > 02/23/2017 13:00:01  03/05/2017 13:00:01
> > > > > krbtgt/[hidden email]
> > > > > 02/23/2017 13:00:01  03/05/2017 13:00:01
> > > > > cifs/[hidden email]
> > > > >
> > > > > [debug.log after mount]
> > > > > Feb 23 13:00:01 trog cifs.upcall: key description:
> > > > > cifs.spnego;0;0;39010000;ver=0x2;host=smb.physics.wisc.edu;ip4=128.104.160
> > > > > .17;sec=krb5;uid=0x0;creduid=0x0;user=[hidden email];pid=0x6abf
> > > > > Feb 23 13:00:01 trog cifs.upcall: ver=2
> > > > > Feb 23 13:00:01 trog cifs.upcall: host=smb.physics.wisc.edu
> > > > > Feb 23 13:00:01 trog cifs.upcall: ip=128.104.160.17
> > > > > Feb 23 13:00:01 trog cifs.upcall: sec=1
> > > > > Feb 23 13:00:01 trog cifs.upcall: uid=0
> > > > > Feb 23 13:00:01 trog cifs.upcall: creduid=0
> > > > > Feb 23 13:00:01 trog cifs.upcall: user=[hidden email]
> > > > > Feb 23 13:00:01 trog cifs.upcall: pid=27327
> > > > > Feb 23 13:00:01 trog cifs.upcall: get_cachename_from_process_env:
> > > > > pathname=/proc/27327/environ
> > > > > Feb 23 13:00:01 trog cifs.upcall: get_existing_cc: default ccache is
> > > > > FILE:/tmp/krb5cc_0
> > > > > Feb 23 13:00:01 trog cifs.upcall: get_tgt_time: unable to get principal
> > > > > Feb 23 13:00:01 trog cifs.upcall: handle_krb5_mech: getting service
> > > > > ticket for smb.physics.wisc.edu
> > > > > Feb 23 13:00:01 trog cifs.upcall: handle_krb5_mech: obtained service ticket
> > > > > Feb 23 13:00:01 trog cifs.upcall: Exit status 0
> > > > > Feb 23 13:00:01 trog cifs.upcall: key description:
> > > > > cifs.spnego;0;0;39010000;ver=0x2;host=smb.physics.wisc.edu;ip4=128.104.160.17;sec=krb5;uid=0x0;creduid=0x0;user=[hidden email];pid=0x6abf
> > > > > Feb 23 13:00:01 trog cifs.upcall: ver=2
> > > > > Feb 23 13:00:01 trog cifs.upcall: host=smb.physics.wisc.edu
> > > > > Feb 23 13:00:01 trog cifs.upcall: ip=128.104.160.17
> > > > > Feb 23 13:00:01 trog cifs.upcall: sec=1
> > > > > Feb 23 13:00:01 trog cifs.upcall: uid=0
> > > > > Feb 23 13:00:01 trog cifs.upcall: creduid=0
> > > > > Feb 23 13:00:01 trog cifs.upcall: user=[hidden email]
> > > > > Feb 23 13:00:01 trog cifs.upcall: pid=27327
> > > > > Feb 23 13:00:01 trog cifs.upcall: get_cachename_from_process_env:
> > > > > pathname=/proc/27327/environ
> > > > > Feb 23 13:00:01 trog cifs.upcall: get_existing_cc: default ccache is
> > > > > FILE:/tmp/krb5cc_0
> > > > > Feb 23 13:00:01 trog cifs.upcall: handle_krb5_mech: getting service
> > > > > ticket for smb.physics.wisc.edu
> > > > > Feb 23 13:00:01 trog cifs.upcall: handle_krb5_mech: obtained service ticket
> > > > > Feb 23 13:00:01 trog cifs.upcall: Exit status 0
> > > > > Feb 23 13:00:01 trog cifs.upcall: key description:
> > > > > cifs.spnego;0;0;39010000;ver=0x2;host=smb.physics.wisc.edu;ip4=128.104.160.17;sec=krb5;uid=0x5d6;creduid=0x5d6;pid=0x6725
> > > > > Feb 23 13:00:01 trog cifs.upcall: ver=2
> > > > > Feb 23 13:00:01 trog cifs.upcall: host=smb.physics.wisc.edu
> > > > > Feb 23 13:00:01 trog cifs.upcall: ip=128.104.160.17
> > > > > Feb 23 13:00:01 trog cifs.upcall: sec=1
> > > > > Feb 23 13:00:01 trog cifs.upcall: uid=1494
> > > > > Feb 23 13:00:01 trog cifs.upcall: creduid=1494
> > > > > Feb 23 13:00:01 trog cifs.upcall: pid=26405
> > > > > Feb 23 13:00:01 trog cifs.upcall: get_cachename_from_process_env:
> > > > > pathname=/proc/26405/environ
> > > > > Feb 23 13:00:01 trog cifs.upcall: get_cachename_from_process_env:
> > > > > cachename = FILE:/tmp/krb5cc_1494_bkfO2z
> > > > > Feb 23 13:00:01 trog cifs.upcall: get_existing_cc: default ccache is
> > > > > FILE:/tmp/krb5cc_1494_bkfO2z
> > > > > Feb 23 13:00:01 trog cifs.upcall: get_tgt_time: unable to
> > > > > gSimo.>
> > > > > > --> To unsubscribe from this list: send the line
> > > > > "unsubscribe linux-cifs" in> the body of a message to
> > > > > [hidden email]> More majordomo info at  http://vge
> > > > > r.kernel.org/majordomo-info.html
> > > > > et principal
> > > > > Feb 23 13:00:01 trog cifs.upcall: Exit status 1
> > > > >
> > > > > cwseys:
> > > > > $ cd /smb
> > > > >
> > > > > [debug.log after cd /smb]
> > > > > Feb 23 13:05:20 trog cifs.upcall: key description:
> > > > > cifs.spnego;0;0;39010000;ver=0x2;host=smb.physics.wisc.edu;ip4=128.104.160.17;sec=krb5;uid=0x5d6;creduid=0x5d6;pid=0x3397
> > > > > Feb 23 13:05:20 trog cifs.upcall: ver=2
> > > > > Feb 23 13:05:20 trog cifs.upcall: host=smb.physics.wisc.edu
> > > > > Feb 23 13:05:20 trog cifs.upcall: ip=128.104.160.17
> > > > > Feb 23 13:05:20 trog cifs.upcall: sec=1
> > > > > Feb 23 13:05:20 trog cifs.upcall: uid=1494
> > > > > Feb 23 13:05:20 trog cifs.upcall: creduid=1494
> > > > > Feb 23 13:05:20 trog cifs.upcall: pid=13207
> > > > > Feb 23 13:05:20 trog cifs.upcall: get_cachename_from_process_env:
> > > > > pathname=/proc/13207/environ
> > > > > Feb 23 13:05:20 trog cifs.upcall: get_cachename_from_process_env:
> > > > > cachename = FILE:/tmp/krb5cc_1494_sM11PG
> > > > > Feb 23 13:05:20 trog cifs.upcall: get_existing_cc: default ccache is
> > > > > FILE:/tmp/krb5cc_1494_sM11PG
> > > > > Feb 23 13:05:20 trog cifs.upcall: handle_krb5_mech: getting service
> > > > > ticket for smb.physics.wisc.edu
> > > > > Feb 23 13:05:20 trog cifs.upcall: handle_krb5_mech: obtained service ticket
> > > > > Feb 23 13:05:20 trog cifs.upcall: Exit status 0
> > > > >
> > > > > $ kdestroy
> > > > > $ ls /tmp/krb5cc_* -al
> > > > > -rw------- 1 root root 1046 Feb 23 13:00 /tmp/krb5cc_0
> > > > >
> > > > > # obs-cos is on a different server - DFS linked.
> > > > > $ cd obs-cos
> > > > > $ ls
> > > > > ls: cannot open directory '.': Permission denied
> > > > >
> > > > > # kerberos cache file created with root owner/group !
> > > > > # The file has bytes in it, but not matching the size above. Wonder
> > > > > # what's in it... ?
> > > > > $ ls /tmp/krb5cc_* -al
> > > > > -rw------- 1 root root 1046 Feb 23 13:00 /tmp/krb5cc_0
> > > > > -rw------- 1 root root 1050 Feb 23 13:05 /tmp/krb5cc_1494_sM11PG
> > > > >
> > > > > # now cannot kinit
> > > > > $ kinit
> > > > > Password for [hidden email]:
> > > > > kinit: Failed to store credentials: Internal credentials cache error
> > > > > (filename: /tmp/krb5cc_1494_sM11PG) while getting initial credentials
> > > > >
> > > > > root:
> > > > > # lets look in the credential cache that was created by root.
> > > > > # looks like credentials used by root to mount /smb:
> > > > > # My guess is the kernel was trying to stash the
> > > > > # cifs/[hidden email]
> > > > > # kerberos ticket, but put it in krb5cc_1494_sM11PG instead
> > > > > # of krb5cc_0
> > > > > # klist -c /tmp/krb5cc_1494_sM11PG
> > > > > Ticket cache: FILE:/tmp/krb5cc_1494_sM11PG
> > > > > Default principal: [hidden email]
> > > > >
> > > > > Valid starting       Expires              Service principal
> > > > > 02/23/2017 13:05:59  03/05/2017 13:05:59
> > > > > krbtgt/[hidden email]
> > > > > 02/23/2017 13:05:59  03/05/2017 13:05:59
> > > > > cifs/[hidden email]
> > > > >
> > > > > # klist -c /tmp/krb5cc_0
> > > > > Ticket cache: FILE:/tmp/krb5cc_0
> > > > > Default principal: [hidden email]
> > > > >
> > > > > Valid starting       Expires              Service principal
> > > > > 02/23/2017 13:00:01  03/05/2017 13:00:01
> > > > > krbtgt/[hidden email]
> > > > > 02/23/2017 13:00:01  03/05/2017 13:00:01
> > > > > cifs/[hidden email]
> > > > >
> > > > > [debug.log after trying to cd obs-cos]
> > > > > vvvvvvvvvvvvvvvvvvvvvvvvvvvv
> > > > > I think the error is here:  Notice pid=13207, that belongs
> > > > > to cwseys but cifs.upcall key description is trying to use uid=0 and
> > > > > creduid=0 . The credential cache file is correct, but the uid/creduid
> > > > > are not.
> > > > >
> > > > > cwseys   13207 /bin/bash
> > > > >
> > > > > Also, in the above the log from 'cd /smb' cifs.upcall used  uid=1494 and
> > > > > creduid=1494 .
> > > > > ^^^^^^^^^^^^^^^^^^^^^^^^^^^
> > > > >
> > > >
> > > > Yep, that's clearly the issue. The question is how you're ending up in
> > > > that situation...
> > > >
> > > > Regardless of how it's happening to you, it's probably possible to fool
> > > > the environment scraping like this, by triggering a krb5 upcall from
> > > > the context of a setuid program that has inherited the KRB5CCNAME
> > > > environment variable from an unprivileged process.
> > > >
> > > > I'm not sure what we can reasonably do about that. I suppose it might
> > > > be interesting to dump the Uid: line from /proc/pid/status when we do
> > > > this upcall, and see what all of the values are set to. Maybe we can
> > > > reject using the credcache if the uid in the upcall doesn't match one
> > > > of the values?
> > > >
> > > > I'll see if I can cook up a debug patch sometime soon for that.
> > > >
> > >
> > > Just out of curiousity. As that unprivileged user, what do you get back
> > >  if you do this?
> > >
> > >     $ which cd ; ls -l `which cd`
> > >
> > > Thanks,
> >
> > Nevermind, I see the problem. From follow_automount in the pathwalking
> > code:
> >
> >         old_cred = override_creds(&init_cred);
> >         mnt = path->dentry->d_op->d_automount(path);
> >         revert_creds(old_cred);
> >
> > So we end up overriding the process creds in order to do the automount,
> > which leads to exactly this problem.
> >
> > I think the best we can do here is probably to just not do the
> > environment scraping if the uid is 0. It's pretty hacky, but hey, we're
> > already in rather nasty hack territory as it is.
> >
> > Thoughts?
>
>
> Can't we detect that the process has changed id ?

How? The credentials are completely overridden with the init_creds once
we get into d_automount.

> Cutting off root may be a way, but I can see how some peoepl may want
> root too to be able to mount and walk cifs shares ...
>
>

Well, root still can with this patch -- just not if his credcache is in
a non-default location.

The other option is to just unset the environment var. That will
probably fix Chad's issue, but my worry there is that root's session
setup can end up being done with the wrong credcache if cwseys had a
valid one when he triggers the automount.

Maybe the right fix is to have mount creds be separate from root's
creds altogether. You'd have a duplicate session for root in most
cases, but maybe that's ok?

--
Jeff Layton <[hidden email]>

Loading...