Linux: Restore aklog -setpag functionality for kernel 2.6.32+
authorMarc Dionne <marc.c.dionne@gmail.com>
Mon, 14 Sep 2009 21:40:23 +0000 (17:40 -0400)
committerDerrick Brashear <shadow|account-1000005@unknown>
Sat, 19 Sep 2009 12:15:31 +0000 (05:15 -0700)
With kernel 2.6.32 it is now possible for a process to copy its session
keyring to its parent through the use of the KEYCTL_SESSION_TO_PARENT
function of the keyctl syscall.

We can't use this easily from kernel space to cover all calls to
VIOCSETTOK with the setpag flag - we'd need to make a syscall
or have keyctl exported.  Instead, a hook is added to ktc_SetToken to
make it honour the AFS_SETTOK_SETPAG flag, which was ineffective with recent
kernels.
This should cover the most common cases (ex: aklog) where this is needed.

The syscall is coded directly to avoid introducing a dependency on the
keyutils library or header files which may not be installed everywhere.

Reviewed-on: http://gerrit.openafs.org/463
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Tested-by: Derrick Brashear <shadow@dementia.org>

acinclude.m4
src/auth/ktc.c
src/cf/linux-test4.m4

index 84423ec..345317a 100644 (file)
@@ -934,6 +934,7 @@ case $AFS_SYSNAME in *_linux* | *_umlinux*)
                 LINUX_KERNEL_HLIST_UNHASHED
                  LINUX_KEY_TYPE_H_EXISTS
                 LINUX_EXPORTS_KEY_TYPE_KEYRING
+                LINUX_KEYS_HAVE_SESSION_TO_PARENT
                 LINUX_NEED_RHCONFIG
                 LINUX_RECALC_SIGPENDING_ARG_TYPE
                 LINUX_SCHED_STRUCT_TASK_STRUCT_HAS_PARENT
index 617c058..c2a39e8 100644 (file)
 
 #endif /* defined(UKERNEL) */
 
+#if defined(LINUX_KEYRING_SUPPORT) && defined(HAVE_SESSION_TO_PARENT)
+#include <sys/syscall.h>
+#define KEYCTL_SESSION_TO_PARENT        18
+#endif
+
 /* For malloc() */
 #include <stdlib.h>
 #include "ktc.h"
@@ -415,6 +420,14 @@ OldSetToken(struct ktc_principal *aserver, struct ktc_token *atoken,
     }
 #else /* NO_AFS_CLIENT */
     code = PIOCTL(0, VIOCSETTOK, &iob, 0);
+#if defined(LINUX_KEYRING_SUPPORT) && defined(HAVE_SESSION_TO_PARENT)
+    /*
+     * If we're using keyring based PAGs and the SESSION_TO_PARENT keyctl
+     * is available, use it to copy the session keyring to the parent process
+     */
+    if (flags & AFS_SETTOK_SETPAG)
+       syscall(SYS_keyctl, KEYCTL_SESSION_TO_PARENT);
+#endif
 #endif /* NO_AFS_CLIENT */
     if (code)
        return KTC_PIOCTLFAIL;
index 866f7af..afc2442 100644 (file)
@@ -1264,3 +1264,15 @@ printk("%s", key_type_keyring.name);
     AC_DEFINE([EXPORTED_KEY_TYPE_KEYRING], 1, [define if key_type_keyring is exported])
   fi])
 
+AC_DEFUN([LINUX_KEYS_HAVE_SESSION_TO_PARENT], [
+  AC_MSG_CHECKING([for KEYCTL_SESSION_TO_PARENT])
+  AC_CACHE_VAL([ac_cv_linux_have_session_to_parent], [
+    AC_TRY_KBUILD(
+[ #include <linux/keyctl.h>],
+[ int i = KEYCTL_SESSION_TO_PARENT;],
+      ac_cv_linux_have_session_to_parent=yes,
+      ac_cv_linux_have_session_to_parent=no)])
+  AC_MSG_RESULT($ac_cv_linux_have_session_to_parent)
+  if test "x$ac_cv_linux_have_session_to_parent" = "xyes"; then
+    AC_DEFINE([HAVE_SESSION_TO_PARENT], 1, [define if keyctl has the KEYCTL_SESSION_TO_PARENT function])
+  fi])