summaryrefslogtreecommitdiff
blob: 64ed5adfcb06876dd98a3541c0e8852b6d2fb4dc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
From eeaabffccffca0bf4c622819da62c6eaa51888bb Mon Sep 17 00:00:00 2001
From: Marc Dionne <marc.c.dionne@gmail.com>
Date: Wed, 9 Jan 2013 19:26:54 -0500
Subject: [PATCH] Linux 3.8: session_keyring changes

The session_keyring is now attached directly to the cred structure
and the thread_group_cred structure (cred->tgcred) no longer exists.

Adapt code that makes use of tgcred, and use the standard rcu based
mechanism to update session_keyring.

Reviewed-on: http://gerrit.openafs.org/8905
Reviewed-by: Andrew Deason <adeason@sinenomine.net>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Derrick Brashear <shadow@your-file-system.com>
(cherry picked from commit c6d27e322a8d3b352554650473a048235a9c763a)

Change-Id: I048ed7b52062a5d666c78dba2599d5fb81c676c1
---
 acinclude.m4                |    1 +
 src/afs/LINUX/osi_compat.h  |   34 ++++++++++++++++++++++++++++++++--
 src/afs/LINUX/osi_groups.c  |    9 ++-------
 src/afs/LINUX/osi_machdep.h |    9 +++++++--
 4 files changed, 42 insertions(+), 11 deletions(-)

diff --git a/acinclude.m4 b/acinclude.m4
index 8c57779..0a05caa 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -812,6 +812,7 @@ case $AFS_SYSNAME in *_linux* | *_umlinux*)
 				       [write_begin], [fs.h])
 		 AC_CHECK_LINUX_STRUCT([backing_dev_info], [name],
 				       [backing-dev.h])
+		 AC_CHECK_LINUX_STRUCT([cred], [session_keyring], [cred.h])
 		 AC_CHECK_LINUX_STRUCT([ctl_table], [ctl_name], [sysctl.h])
 		 AC_CHECK_LINUX_STRUCT([dentry_operations], [d_automount], [dcache.h])
 		 AC_CHECK_LINUX_STRUCT([inode], [i_alloc_sem], [fs.h])
diff --git a/src/afs/LINUX/osi_compat.h b/src/afs/LINUX/osi_compat.h
index 2dda136..a777542 100644
--- a/src/afs/LINUX/osi_compat.h
+++ b/src/afs/LINUX/osi_compat.h
@@ -186,14 +186,24 @@ afs_linux_key_alloc(struct key_type *type, const char *desc, uid_t uid,
 }
 
 # if defined(STRUCT_TASK_STRUCT_HAS_CRED)
+static inline struct key *
+afs_session_keyring(afs_ucred_t *cred)
+{
+#  if defined(STRUCT_CRED_HAS_SESSION_KEYRING)
+    return cred->session_keyring;
+#  else
+    return cred->tgcred->session_keyring;
+#  endif
+}
+
 static inline struct key*
 afs_linux_search_keyring(afs_ucred_t *cred, struct key_type *type)
 {
     key_ref_t key_ref;
 
-    if (cred->tgcred->session_keyring) {
+    if (afs_session_keyring(cred)) {
 	key_ref = keyring_search(
-		      make_key_ref(cred->tgcred->session_keyring, 1),
+		      make_key_ref(afs_session_keyring(cred), 1),
 		      type, "_pag");
 	if (IS_ERR(key_ref))
 	    return ERR_CAST(key_ref);
@@ -507,4 +517,24 @@ afs_set_name(afs_name_t aname, char *string) {
 }
 #endif
 
+static_inline struct key *
+afs_set_session_keyring(struct key *keyring)
+{
+    struct key *old;
+#if defined(STRUCT_CRED_HAS_SESSION_KEYRING)
+    struct cred *new_creds;
+    old = current_session_keyring();
+    new_creds = prepare_creds();
+    rcu_assign_pointer(new_creds->session_keyring, keyring);
+    commit_creds(new_creds);
+#else
+    spin_lock_irq(&current->sighand->siglock);
+    old = task_session_keyring(current);
+    smp_wmb();
+    task_session_keyring(current) = keyring;
+    spin_unlock_irq(&current->sighand->siglock);
+#endif
+    return old;
+}
+
 #endif /* AFS_LINUX_OSI_COMPAT_H */
diff --git a/src/afs/LINUX/osi_groups.c b/src/afs/LINUX/osi_groups.c
index c2a0308..e351344 100644
--- a/src/afs/LINUX/osi_groups.c
+++ b/src/afs/LINUX/osi_groups.c
@@ -214,14 +214,9 @@ install_session_keyring(struct key *keyring)
     }
 
     /* install the keyring */
-    spin_lock_irq(&current->sighand->siglock);
-    old = task_session_keyring(current);
-    smp_wmb();
-    task_session_keyring(current) = keyring;
-    spin_unlock_irq(&current->sighand->siglock);
-
+    old = afs_set_session_keyring(keyring);
     if (old)
-	    key_put(old);
+	key_put(old);
 
 out:
     return code;
diff --git a/src/afs/LINUX/osi_machdep.h b/src/afs/LINUX/osi_machdep.h
index 9260733..0202d0d 100644
--- a/src/afs/LINUX/osi_machdep.h
+++ b/src/afs/LINUX/osi_machdep.h
@@ -179,8 +179,13 @@ afs_set_cr_group_info(cred_t *cred, struct group_info *group_info) {
 # define current_group_info() (current->cred->group_info)
 # define task_gid(task) (task->cred->gid)
 # define task_user(task) (task->cred->user)
-# define task_session_keyring(task) (task->cred->tgcred->session_keyring)
-# define current_session_keyring() (current->cred->tgcred->session_keyring)
+# if defined(STRUCT_CRED_HAS_SESSION_KEYRING)
+#  define task_session_keyring(task) (task->cred->session_keyring)
+#  define current_session_keyring() (current->cred->session_keyring)
+# else
+#  define task_session_keyring(task) (task->cred->tgcred->session_keyring)
+#  define current_session_keyring() (current->cred->tgcred->session_keyring)
+# endif
 
 #else
 
-- 
1.7.2.5