[nfs-utils/private-jlayton-gssd-1] gssd: make it fork and switch creds before acquiring GSSAPI creds
Jeff Layton
jlayton at fedoraproject.org
Tue Oct 15 00:34:11 UTC 2013
commit ffb034487896382266514ef364c8eba4722486ee
Author: Jeff Layton <jlayton at redhat.com>
Date: Mon Oct 14 20:27:31 2013 -0400
gssd: make it fork and switch creds before acquiring GSSAPI creds
Signed-off-by: Jeff Layton <jlayton at redhat.com>
nfs-utils-1.2.9-gssd-switch-creds.patch | 166 +++++++++++++++++++++++++++++++
nfs-utils.spec | 9 ++-
2 files changed, 174 insertions(+), 1 deletions(-)
---
diff --git a/nfs-utils-1.2.9-gssd-switch-creds.patch b/nfs-utils-1.2.9-gssd-switch-creds.patch
new file mode 100644
index 0000000..264faaf
--- /dev/null
+++ b/nfs-utils-1.2.9-gssd-switch-creds.patch
@@ -0,0 +1,166 @@
+diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
+index e58c341..b48d163 100644
+--- a/utils/gssd/gssd_proc.c
++++ b/utils/gssd/gssd_proc.c
+@@ -67,6 +67,8 @@
+ #include <errno.h>
+ #include <gssapi/gssapi.h>
+ #include <netdb.h>
++#include <sys/types.h>
++#include <sys/wait.h>
+
+ #include "gssd.h"
+ #include "err_util.h"
+@@ -832,7 +834,6 @@ create_auth_rpc_client(struct clnt_info *clp,
+ CLIENT *rpc_clnt = NULL;
+ struct rpc_gss_sec sec;
+ AUTH *auth = NULL;
+- uid_t save_uid = -1;
+ int retval = -1;
+ OM_uint32 min_stat;
+ char rpc_errmsg[1024];
+@@ -841,16 +842,6 @@ create_auth_rpc_client(struct clnt_info *clp,
+ struct sockaddr *addr = (struct sockaddr *) &clp->addr;
+ socklen_t salen;
+
+- /* Create the context as the user (not as root) */
+- save_uid = geteuid();
+- if (setfsuid(uid) != 0) {
+- printerr(0, "WARNING: Failed to setfsuid for "
+- "user with uid %d\n", uid);
+- goto out_fail;
+- }
+- printerr(2, "creating context using fsuid %d (save_uid %d)\n",
+- uid, save_uid);
+-
+ sec.qop = GSS_C_QOP_DEFAULT;
+ sec.svc = RPCSEC_GSS_SVC_NONE;
+ sec.cred = cred;
+@@ -949,11 +940,6 @@ create_auth_rpc_client(struct clnt_info *clp,
+ out:
+ if (sec.cred != GSS_C_NO_CREDENTIAL)
+ gss_release_cred(&min_stat, &sec.cred);
+- /* Restore euid to original value */
+- if (((int)save_uid != -1) && (setfsuid(save_uid) != (int)uid)) {
+- printerr(0, "WARNING: Failed to restore fsuid"
+- " to uid %d from %d\n", save_uid, uid);
+- }
+ return retval;
+
+ out_fail:
+@@ -964,6 +950,64 @@ create_auth_rpc_client(struct clnt_info *clp,
+ }
+
+ /*
++ * Create the context as the user (not as root).
++ *
++ * Note that we change the *real* uid here, as changing the effective uid is
++ * not sufficient. This is due to an unfortunate historical error in the MIT
++ * krb5 libs, where they used %{uid} in the default_ccache_name. Changing that
++ * now might break some applications so we're sort of stuck with it.
++ *
++ * Unfortunately, doing this leaves the forked child vulnerable to signals and
++ * renicing, but this is the best we can do. In the event that a child is
++ * signalled before downcalling, the kernel will just eventually time out the
++ * upcall attempt.
++ */
++static int
++change_identity(uid_t uid)
++{
++ struct passwd *pw;
++
++ /* drop list of supplimentary groups first */
++ if (setgroups(0, NULL) != 0) {
++ printerr(0, "WARNING: unable to drop supplimentary groups!");
++ return errno;
++ }
++
++ /* try to get pwent for user */
++ pw = getpwuid(uid);
++ if (!pw) {
++ /* if that doesn't work, try to get one for "nobody" */
++ errno = 0;
++ pw = getpwnam("nobody");
++ if (!pw) {
++ printerr(0, "WARNING: unable to determine gid for uid %u\n", uid);
++ return errno ? errno : ENOENT;
++ }
++ }
++
++ /*
++ * Switch the GIDs. Note that we leave the saved-set-gid alone in an
++ * attempt to prevent attacks via ptrace()
++ */
++ if (setresgid(pw->pw_gid, pw->pw_gid, -1) != 0) {
++ printerr(0, "WARNING: failed to set gid to %u!\n", pw->pw_gid);
++ return errno;
++ }
++
++ /*
++ * Switch UIDs, but leave saved-set-uid alone to prevent ptrace() by
++ * other processes running with this uid.
++ */
++ if (setresuid(uid, uid, -1) != 0) {
++ printerr(0, "WARNING: Failed to setuid for user with uid %u\n",
++ uid);
++ return errno;
++ }
++
++ return 0;
++}
++
++/*
+ * this code uses the userland rpcsec gss library to create a krb5
+ * context on behalf of the kernel
+ */
+@@ -982,6 +1026,26 @@ process_krb5_upcall(struct clnt_info *clp, uid_t uid, int fd, char *tgtname,
+ int err, downcall_err = -EACCES;
+ gss_cred_id_t gss_cred;
+ OM_uint32 maj_stat, min_stat, lifetime_rec;
++ pid_t pid;
++
++ pid = fork();
++ switch(pid) {
++ case 0:
++ /* Child: fall through to rest of function */
++ break;
++ case -1:
++ /* fork() failed! */
++ printerr(0, "WARNING: unable to fork() to handle upcall: %s\n",
++ strerror(errno));
++ return;
++ default:
++ /* Parent: just wait on child to exit and return */
++ wait(&err);
++ if (WIFSIGNALED(err))
++ printerr(0, "WARNING: forked child was killed with signal %d\n",
++ WTERMSIG(err));
++ return;
++ }
+
+ printerr(1, "handling krb5 upcall (%s)\n", clp->dirname);
+
+@@ -1014,6 +1078,14 @@ process_krb5_upcall(struct clnt_info *clp, uid_t uid, int fd, char *tgtname,
+ service ? service : "<null>");
+ if (uid != 0 || (uid == 0 && root_uses_machine_creds == 0 &&
+ service == NULL)) {
++
++ err = change_identity(uid);
++ if (err) {
++ printerr(0, "WARNING: failed to change identity: %s",
++ strerror(err));
++ goto out_return_error;
++ }
++
+ /* Tell krb5 gss which credentials cache to use */
+ /* Try first to acquire credentials directly via GSSAPI */
+ err = gssd_acquire_user_cred(uid, &gss_cred);
+@@ -1121,7 +1193,7 @@ out:
+ AUTH_DESTROY(auth);
+ if (rpc_clnt)
+ clnt_destroy(rpc_clnt);
+- return;
++ exit(0);
+
+ out_return_error:
+ do_error_downcall(fd, uid, downcall_err);
diff --git a/nfs-utils.spec b/nfs-utils.spec
index 9fae510..077c58b 100644
--- a/nfs-utils.spec
+++ b/nfs-utils.spec
@@ -2,7 +2,7 @@ Summary: NFS utilities and supporting clients and daemons for the kernel NFS ser
Name: nfs-utils
URL: http://sourceforge.net/projects/nfs
Version: 1.2.8
-Release: 6.0%{?dist}
+Release: 6.0.gssd.1%{?dist}
Epoch: 1
# group all 32bit related archs
@@ -43,6 +43,8 @@ Patch101: nfs-utils-1.2.1-exp-subtree-warn-off.patch
Patch102: nfs-utils-1.2.3-sm-notify-res_init.patch
Patch103: nfs-utils-1.2.5-idmap-errmsg.patch
+Patch201: nfs-utils-1.2.9-gssd-switch-creds.patch
+
Group: System Environment/Daemons
Provides: exportfs = %{epoch}:%{version}-%{release}
Provides: nfsstat = %{epoch}:%{version}-%{release}
@@ -100,6 +102,8 @@ This package also contains the mount.nfs and umount.nfs program.
%patch102 -p1
%patch103 -p1
+%patch201 -p1
+
# Remove .orig files
find . -name "*.orig" | xargs rm -f
@@ -312,6 +316,9 @@ fi
/sbin/umount.nfs4
%changelog
+* Mon Oct 14 2013 Steve Dickson <steved at redhat.com> 1.2.8-6.0.gssd.1
+- make gssd fork and switch creds before acquiring GSSAPI creds
+
* Tue Sep 24 2013 Steve Dickson <steved at redhat.com> 1.2.8-6.0
- Updated to latest upstream RC release: nfs-utils-1-2-9-rc6
More information about the scm-commits
mailing list