aboutsummaryrefslogtreecommitdiffstats
path: root/security/keys
diff options
context:
space:
mode:
Diffstat (limited to 'security/keys')
-rw-r--r--security/keys/proc.c77
1 files changed, 55 insertions, 22 deletions
diff --git a/security/keys/proc.c b/security/keys/proc.c
index 39793c774f33..624c650c2efd 100644
--- a/security/keys/proc.c
+++ b/security/keys/proc.c
@@ -91,57 +91,90 @@ __initcall(key_proc_init);
91 */ 91 */
92#ifdef CONFIG_KEYS_DEBUG_PROC_KEYS 92#ifdef CONFIG_KEYS_DEBUG_PROC_KEYS
93 93
94static struct rb_node *__key_serial_next(struct rb_node *n) 94static struct rb_node *key_serial_next(struct rb_node *n)
95{ 95{
96 struct user_namespace *user_ns = current_user_ns();
97
98 n = rb_next(n);
96 while (n) { 99 while (n) {
97 struct key *key = rb_entry(n, struct key, serial_node); 100 struct key *key = rb_entry(n, struct key, serial_node);
98 if (key->user->user_ns == current_user_ns()) 101 if (key->user->user_ns == user_ns)
99 break; 102 break;
100 n = rb_next(n); 103 n = rb_next(n);
101 } 104 }
102 return n; 105 return n;
103} 106}
104 107
105static struct rb_node *key_serial_next(struct rb_node *n) 108static int proc_keys_open(struct inode *inode, struct file *file)
106{ 109{
107 return __key_serial_next(rb_next(n)); 110 return seq_open(file, &proc_keys_ops);
108} 111}
109 112
110static struct rb_node *key_serial_first(struct rb_root *r) 113static struct key *find_ge_key(key_serial_t id)
111{ 114{
112 struct rb_node *n = rb_first(r); 115 struct user_namespace *user_ns = current_user_ns();
113 return __key_serial_next(n); 116 struct rb_node *n = key_serial_tree.rb_node;
114} 117 struct key *minkey = NULL;
115 118
116static int proc_keys_open(struct inode *inode, struct file *file) 119 while (n) {
117{ 120 struct key *key = rb_entry(n, struct key, serial_node);
118 return seq_open(file, &proc_keys_ops); 121 if (id < key->serial) {
122 if (!minkey || minkey->serial > key->serial)
123 minkey = key;
124 n = n->rb_left;
125 } else if (id > key->serial) {
126 n = n->rb_right;
127 } else {
128 minkey = key;
129 break;
130 }
131 key = NULL;
132 }
119 133
134 if (!minkey)
135 return NULL;
136
137 for (;;) {
138 if (minkey->user->user_ns == user_ns)
139 return minkey;
140 n = rb_next(&minkey->serial_node);
141 if (!n)
142 return NULL;
143 minkey = rb_entry(n, struct key, serial_node);
144 }
120} 145}
121 146
122static void *proc_keys_start(struct seq_file *p, loff_t *_pos) 147static void *proc_keys_start(struct seq_file *p, loff_t *_pos)
123 __acquires(key_serial_lock) 148 __acquires(key_serial_lock)
124{ 149{
125 struct rb_node *_p; 150 key_serial_t pos = *_pos;
126 loff_t pos = *_pos; 151 struct key *key;
127 152
128 spin_lock(&key_serial_lock); 153 spin_lock(&key_serial_lock);
129 154
130 _p = key_serial_first(&key_serial_tree); 155 if (*_pos > INT_MAX)
131 while (pos > 0 && _p) { 156 return NULL;
132 pos--; 157 key = find_ge_key(pos);
133 _p = key_serial_next(_p); 158 if (!key)
134 } 159 return NULL;
135 160 *_pos = key->serial;
136 return _p; 161 return &key->serial_node;
162}
137 163
164static inline key_serial_t key_node_serial(struct rb_node *n)
165{
166 struct key *key = rb_entry(n, struct key, serial_node);
167 return key->serial;
138} 168}
139 169
140static void *proc_keys_next(struct seq_file *p, void *v, loff_t *_pos) 170static void *proc_keys_next(struct seq_file *p, void *v, loff_t *_pos)
141{ 171{
142 (*_pos)++; 172 struct rb_node *n;
143 return key_serial_next((struct rb_node *) v);
144 173
174 n = key_serial_next(v);
175 if (n)
176 *_pos = key_node_serial(n);
177 return n;
145} 178}
146 179
147static void proc_keys_stop(struct seq_file *p, void *v) 180static void proc_keys_stop(struct seq_file *p, void *v)