diff mbox

[cifs-utils,RFC] cifs.upcall: don't do env scraping when uid is 0

Message ID 20170223215835.18490-1-jlayton@samba.org (mailing list archive)
State New, archived
Headers show

Commit Message

Jeff Layton Feb. 23, 2017, 9:58 p.m. UTC
Setuid programs triggering upcalls could trick the program here. Also,
the d_automount method is done with credentials overridden so if you
can end up with mismatched creds and env vars due to that as well.

It's a hack, but the only recourse I can see is to avoid doing this
when the uid is 0. That means we can rely on this for getting to root's
credcache, but hopefully that's not a huge issue.

Reported-by: Chad William Seys <cwseys@physics.wisc.edu>
Signed-off-by: Jeff Layton <jlayton@samba.org>
---
 cifs.upcall.8.in |  5 ++++-
 cifs.upcall.c    | 10 +++++++++-
 2 files changed, 13 insertions(+), 2 deletions(-)

Comments

Jeff Layton Feb. 23, 2017, 11:24 p.m. UTC | #1
On Thu, 2017-02-23 at 16:58 -0500, Jeff Layton wrote:
> Setuid programs triggering upcalls could trick the program here. Also,
> the d_automount method is done with credentials overridden so if you
> can end up with mismatched creds and env vars due to that as well.
> 
> It's a hack, but the only recourse I can see is to avoid doing this
> when the uid is 0. That means we can rely on this for getting to root's
> credcache, but hopefully that's not a huge issue.
> 
> Reported-by: Chad William Seys <cwseys@physics.wisc.edu>
> Signed-off-by: Jeff Layton <jlayton@samba.org>
> ---
>  cifs.upcall.8.in |  5 ++++-
>  cifs.upcall.c    | 10 +++++++++-
>  2 files changed, 13 insertions(+), 2 deletions(-)
> 
> diff --git a/cifs.upcall.8.in b/cifs.upcall.8.in
> index e1f3956e176a..81481a482fb4 100644
> --- a/cifs.upcall.8.in
> +++ b/cifs.upcall.8.in
> @@ -44,7 +44,10 @@ 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.
> +credcaches in the default locations specified in krb5.conf. Note that this is
> +never performed when the uid is 0. The default credcache location is always
> +used when the uid is 0, regardless of the environment variable setting in the
> +process.
>  .RE
>  .PP
>  \--krb5conf=/path/to/krb5.conf|-k /path/to/krb5.conf
> diff --git a/cifs.upcall.c b/cifs.upcall.c
> index f766a8b5799e..8f6bb761a27e 100644
> --- a/cifs.upcall.c
> +++ b/cifs.upcall.c
> @@ -1018,11 +1018,19 @@ int main(const int argc, char *const argv[])
>  	}
>  
>  	/*
> +	 * We can't reasonably do this for root. Mounting a DFS share, for
> +	 * instance we can end up with creds being overridden, but the env
> +	 * variable left intact.
> +	 */
> +	if (uid == 0)
> +		env_probe = false;
> +
> +	/*
>  	 * 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);
> +		get_cachename_from_process_env(env_probe ? arg.pid : 0);
>  
>  	rc = setuid(uid);
>  	if (rc == -1) {


Actually...what may be better here is to just unset KRB5CCNAME after we
try to find an existing credcache, but before we try to set one up from
the keytab. I see no need to use the environment var at all when we
expect to instantiate a new ccache.

Now that I think about it though, we might still want to restrict root
like this too. In particular, we could end up performing session setup
for root's session from the wrong credcache. I don't think that's quite
what we want there. 

So I think we'll want to keep this patch, and have it unset the
environment var too. There's probably some way to do all of this more
cleanly from a namespace standpoint, but I'm not sure how...
diff mbox

Patch

diff --git a/cifs.upcall.8.in b/cifs.upcall.8.in
index e1f3956e176a..81481a482fb4 100644
--- a/cifs.upcall.8.in
+++ b/cifs.upcall.8.in
@@ -44,7 +44,10 @@  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.
+credcaches in the default locations specified in krb5.conf. Note that this is
+never performed when the uid is 0. The default credcache location is always
+used when the uid is 0, regardless of the environment variable setting in the
+process.
 .RE
 .PP
 \--krb5conf=/path/to/krb5.conf|-k /path/to/krb5.conf
diff --git a/cifs.upcall.c b/cifs.upcall.c
index f766a8b5799e..8f6bb761a27e 100644
--- a/cifs.upcall.c
+++ b/cifs.upcall.c
@@ -1018,11 +1018,19 @@  int main(const int argc, char *const argv[])
 	}
 
 	/*
+	 * We can't reasonably do this for root. Mounting a DFS share, for
+	 * instance we can end up with creds being overridden, but the env
+	 * variable left intact.
+	 */
+	if (uid == 0)
+		env_probe = false;
+
+	/*
 	 * 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);
+		get_cachename_from_process_env(env_probe ? arg.pid : 0);
 
 	rc = setuid(uid);
 	if (rc == -1) {