]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
STABLE14-linux-keyring-pags-20060804
authorChas Williams <chas@cmf.nrl.navy.mil>
Mon, 14 Aug 2006 23:09:30 +0000 (23:09 +0000)
committerDerrick Brashear <shadow@dementia.org>
Mon, 14 Aug 2006 23:09:30 +0000 (23:09 +0000)
ok, well, first try

(cherry picked from commit 43f1bcf65ae1f75694510524d9cb2d8fffcc5992)

acinclude.m4
src/afs/LINUX/osi_groups.c
src/afs/LINUX/osi_module.c
src/afs/LINUX/osi_prototypes.h
src/afs/afs_osi_pag.c
src/afs/sysincludes.h

index 60dcafc8a26d8eb1d8dc5f4278c8effec08946bc..116224613f58d3da0f58539aaf822c73b2bee16f 100644 (file)
@@ -602,6 +602,8 @@ case $AFS_SYSNAME in *_linux* | *_umlinux*)
                 LINUX_SCHED_STRUCT_TASK_STRUCT_HAS_SIGNAL_RLIM
                 LINUX_SCHED_STRUCT_TASK_STRUCT_HAS_EXIT_STATE
                 LINUX_REFRIGERATOR
+                LINUX_LINUX_KEYRING_SUPPORT
+                LINUX_KEY_ALLOC_NEEDS_STRUCT_TASK
                 LINUX_WHICH_MODULES
                  if test "x$ac_cv_linux_config_modversions" = "xno" -o $AFS_SYSKVERS -ge 26; then
                    AC_MSG_WARN([Cannot determine sys_call_table status. assuming it isn't exported])
index 8a4e2d2e1206d7fd1629ecc191957e83ae037dee..bf2117296347c53546faeabbbd3e156bb2f55350 100644 (file)
@@ -15,6 +15,9 @@
  */
 #include <afsconfig.h>
 #include "afs/param.h"
+#ifdef LINUX_KEYRING_SUPPORT
+#include <linux/seq_file.h>
+#endif
 
 RCSID
     ("$Header$");
@@ -148,11 +151,11 @@ set_pag_in_parent(int pag, int g0, int g1)
 }
 #endif
 
+#if defined(AFS_LINUX26_ENV)
 int
-setpag(cred_t ** cr, afs_uint32 pagvalue, afs_uint32 * newpag,
-       int change_parent)
+__setpag(cred_t ** cr, afs_uint32 pagvalue, afs_uint32 * newpag,
+         int change_parent)
 {
-#if defined(AFS_LINUX26_ENV)
     struct group_info *group_info;
     gid_t g0, g1;
     struct group_info *tmp;
@@ -185,7 +188,64 @@ setpag(cred_t ** cr, afs_uint32 pagvalue, afs_uint32 * newpag,
     put_group_info(group_info);
 
     return 0;
+}
+
+#ifdef LINUX_KEYRING_SUPPORT
+#include <asm/unistd.h>
+#include <linux/keyctl.h>
+
+static int errno;
+static inline _syscall2(long, keyctl, int, option, void*, arg2);
+
+static long
+__join_session_keyring(char *name)
+{
+       return keyctl(KEYCTL_JOIN_SESSION_KEYRING, name);
+}
+#endif /* LINUX_KEYRING_SUPPORT */
+
+int
+setpag(cred_t ** cr, afs_uint32 pagvalue, afs_uint32 * newpag,
+         int change_parent)
+{
+    int code;
+
+    code = __setpag(cr, pagvalue, newpag, change_parent);
+
+#ifdef LINUX_KEYRING_SUPPORT
+    if (code == 0) {
+
+       (void) __join_session_keyring(NULL);
+
+       if (current->signal->session_keyring) {
+           struct key *key;
+           key_perm_t perm;
+
+           perm = KEY_POS_VIEW | KEY_POS_SEARCH;
+           perm |= KEY_USR_VIEW | KEY_USR_SEARCH;
+
+#ifdef KEY_ALLOC_NEEDS_STRUCT_TASK
+           key = key_alloc(&key_type_afs_pag, "_pag", 0, 0, current, perm, 1);
+#else
+           key = key_alloc(&key_type_afs_pag, "_pag", 0, 0, perm, 1);
+#endif
+
+           if (!IS_ERR(key)) {
+               key_instantiate_and_link(key, (void *) newpag, sizeof(afs_uint32),
+                                        current->signal->session_keyring, NULL);
+               key_put(key);
+           }
+       }
+    }
+#endif /* LINUX_KEYRING_SUPPORT */
+
+    return code;
+}
 #else
+int
+setpag(cred_t ** cr, afs_uint32 pagvalue, afs_uint32 * newpag,
+       int change_parent)
+{
     gid_t *gidset;
     afs_int32 ngroups, code = 0;
     int j;
@@ -219,8 +279,8 @@ setpag(cred_t ** cr, afs_uint32 pagvalue, afs_uint32 * newpag,
 
     osi_Free((char *)gidset, NGROUPS * sizeof(int));
     return code;
-#endif
 }
+#endif
 
 
 /* Intercept the standard system call. */
@@ -396,3 +456,86 @@ afs32_xsetgroups32(int gidsetsize, gid_t * grouplist)
 #endif
 #endif
 
+
+#ifdef LINUX_KEYRING_SUPPORT
+static void afs_pag_describe(const struct key *key, struct seq_file *m)
+{
+    seq_puts(m, key->description);
+
+    seq_printf(m, ": %u", key->datalen);
+}
+
+static int afs_pag_instantiate(struct key *key, const void *data, size_t datalen)
+{
+    int code;
+    afs_uint32 *userpag, pag = NOPAG;
+    int g0, g1;
+
+    if (key->uid != 0 || key->gid != 0)
+       return -EPERM;
+
+    code = -EINVAL;
+    get_group_info(current->group_info);
+
+    if (datalen != sizeof(afs_uint32) || !data)
+       goto error;
+
+    if (current->group_info->ngroups < 2)
+       goto error;
+
+    /* ensure key being set matches current pag */
+
+    g0 = GROUP_AT(current->group_info, 0);
+    g1 = GROUP_AT(current->group_info, 1);
+
+    pag = afs_get_pag_from_groups(g0, g1);
+    if (pag == NOPAG)
+       goto error;
+
+    userpag = (afs_uint32 *) data;
+    if (*userpag != pag)
+       goto error;
+
+    key->payload.value = (unsigned long) *userpag;
+    key->datalen = sizeof(afs_uint32);
+    code = 0;
+
+error:
+    put_group_info(current->group_info);
+    return code;
+}
+
+static int afs_pag_match(const struct key *key, const void *description)
+{
+       return strcmp(key->description, description) == 0;
+}
+
+struct key_type key_type_afs_pag =
+{
+    .name        = "afs_pag",
+    .describe    = afs_pag_describe,
+    .instantiate = afs_pag_instantiate,
+    .match       = afs_pag_match,
+};
+
+void osi_keyring_init(void)
+{
+    register_key_type(&key_type_afs_pag);
+}
+
+void osi_keyring_shutdown(void)
+{
+    unregister_key_type(&key_type_afs_pag);
+}
+
+#else
+void osi_keyring_init(void)
+{
+       return;
+}
+
+void osi_keyring_shutdown(void)
+{
+       return;
+}
+#endif
index 1e79a8af2e82690204965f6d27dcabf9405006eb..067a5bb3217e74a2e681df4cd005a4e438f01840 100644 (file)
@@ -366,14 +366,19 @@ init_module(void)
 
     osi_Init();
 
+#ifndef LINUX_KEYRING_SUPPORT
     err = osi_syscall_init();
     if (err)
        return err;
+#endif
     err = afs_init_inodecache();
     if (err)
        return err;
     register_filesystem(&afs_fs_type);
     osi_sysctl_init();
+#ifdef LINUX_KEYRING_SUPPORT
+    osi_keyring_init();
+#endif
 #ifdef AFS_LINUX24_ENV
     afsproc_init();
 #endif
@@ -389,6 +394,7 @@ void
 cleanup_module(void)
 #endif
 {
+    osi_keyring_shutdown();
     osi_sysctl_clean();
     osi_syscall_clean();
     unregister_filesystem(&afs_fs_type);
index bf8b88ca6d567843fe8c195d703a68b3d44ab560..c86bab6a47a29799c5793392fd8536ace40cdd84 100644 (file)
@@ -67,4 +67,14 @@ extern void afs_destroy_inodecache(void);
 /* osi_vnodeops.c */
 extern void afs_fill_inode(struct inode *ip, struct vattr *vattr);
 
+/* osi_groups.c */
+extern void osi_keyring_init(void);
+extern void osi_keyring_shutdown(void);
+extern int __setpag(cred_t **cr, afs_uint32 pagvalue, afs_uint32 *newpag,
+                    int change_parent);
+#ifdef LINUX_KEYRING_SUPPORT
+extern struct key_type key_type_afs_pag;
+#endif /* LINUX_KEYRING_SUPPORT */
+
+
 #endif /* _OSI_PROTO_H_ */
index 8d49baf53851db182a1496829441290c74775fc9..00d6f0dbe60743c6e14bcb790ca83818c4f04f56 100644 (file)
@@ -453,8 +453,6 @@ afs_get_pag_from_groups(gid_t g0a, gid_t g1a)
        /* Additional testing */
        if (((ret >> 24) & 0xff) == 'A')
            return ret;
-       else
-           return NOPAG;
 #endif /* UKERNEL && AFS_WEB_ENHANCEMENTS */
     }
     return NOPAG;
@@ -487,7 +485,7 @@ PagInCred(const struct AFS_UCRED *cred)
     gid_t g0, g1;
 
     AFS_STATCNT(PagInCred);
-    if (cred == NULL) {
+    if (cred == NULL || cred == afs_osi_credp) {
        return NOPAG;
     }
 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
@@ -509,11 +507,15 @@ PagInCred(const struct AFS_UCRED *cred)
        return NOPAG;
     }
 #elif defined(AFS_LINUX26_ENV)
-    if (cred->cr_group_info->ngroups < 2)
-       return NOPAG;
+    if (cred->cr_group_info->ngroups < 2) {
+       pag = NOPAG;
+       goto out;
+    }
 #elif defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_DUX40_ENV) || defined(AFS_LINUX20_ENV) || defined(AFS_XBSD_ENV)
-    if (cred->cr_ngroups < 2)
-       return NOPAG;
+    if (cred->cr_ngroups < 2) {
+       pag = NOPAG;
+       goto out;
+    }
 #endif
 #if defined(AFS_AIX51_ENV)
     g0 = cred->cr_groupset.gs_union.un_groups[0];
@@ -527,5 +529,23 @@ PagInCred(const struct AFS_UCRED *cred)
 #endif
 #endif
     pag = (afs_int32) afs_get_pag_from_groups(g0, g1);
+out:
+#ifdef LINUX_KEYRING_SUPPORT
+    if (pag == NOPAG) {
+       struct key *key;
+       afs_uint32 pag, newpag;
+
+       key = request_key(&key_type_afs_pag, "_pag", NULL);
+       if (!IS_ERR(key)) {
+           if (key_validate(key) == 0 && key->uid == 0) {      /* also verify in the session keyring? */
+
+               pag = (afs_uint32) key->payload.value;
+               if (((pag >> 24) & 0xff) == 'A')
+                   __setpag(&cred, pag, &newpag, 0);
+           }
+           key_put(key);
+       } 
+    }
+#endif
     return pag;
 }
index e67c7bc3383ebe8e907a56398a27e855e9418fa6..22fe7a684e738f6a7878e904fdbb985797591ad5 100644 (file)
 #include <linux/security.h>
 #endif
 #include <linux/suspend.h>
+#if defined(LINUX_KEYRING_SUPPORT)
+#include <linux/rwsem.h>
+#include <linux/key.h>
+#endif
 #endif
 /* Avoid conflicts with coda overloading AFS type namespace. Must precede
  * inclusion of uaccess.h.